package cn.huiyunche.base.service.interfaces.impl;

import cn.huiyunche.base.service.constant.TmsUrlConstant;
import cn.huiyunche.base.service.enums.*;
import cn.huiyunche.base.service.form.AttachForm;
import cn.huiyunche.base.service.framework.utils.QiniuUtils;
import cn.huiyunche.base.service.framework.utils.TmsQueueApi;
import cn.huiyunche.base.service.interfaces.*;
import cn.huiyunche.base.service.mappers.*;
import cn.huiyunche.base.service.mappers.ext.DNoticeViewMapper;
import cn.huiyunche.base.service.mappers.ext.DUserViewMapper;
import cn.huiyunche.base.service.mappers.ext.DWaybillViewMapper;
import cn.huiyunche.base.service.model.*;
import cn.huiyunche.base.service.utils.DateUtils;
import cn.huiyunche.base.service.utils.JavaSmsApi;
import cn.huiyunche.base.service.vo.*;
import cn.huiyunche.base.service.vo.detail.OrderPriceInfo;
import cn.huiyunche.tools.basic.exceptions.BusinessException;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Strings;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

/**
 * The type D waybill service.
 *
 * @FileName: cn.huiyunche.app.service.tms.interfaces.impl
 * @Description: Description
 * @author: Aaron
 * @date: 2016 /11/2 上午11:14
 */
@Service
public class DWaybillServiceImpl implements DWaybillService {

    private static final Logger LOGGER = LoggerFactory.getLogger(DWaybillServiceImpl.class);

    //油费补贴
    private static final String OIL_SUBSIDY_FEE_NAME = "油费补贴";

    //基础运费
    private static final String SHIPPING_FEE_NAME = "基础运费";

    //总费用
    private static final String TOTAL_SHIPPING_FEE_NAME = "总费用";

    @Autowired
    private BTransportModeService bTransportModeService;

    @Autowired
    private BWarehouseService bWareHouseService;

    @Autowired
    private BDealerService bDealerService;

    @Autowired
    private BDealerDistributaryService bDealerDistributaryService;

    @Autowired
    private DWaybillMapper dWaybillMapper;

    @Autowired
    private DWaybillVehicleService dWaybillVehicleService;

    @Autowired
    private DWaybillReceiverService dWaybillReceiverService;

    @Autowired
    private BVehicleTypeService bVehicleTypeService;

    @Autowired
    private DWaybillFeeTypeService dWaybillFeeTypeService;

    @Autowired
    private DWaybillFeeDetailService dWaybillFeeDetailService;

    @Autowired
    private SendMessageService sendMessageService;

    @Autowired
    private TmsOrderCallHistoryServiceImpl tmsOrderCallHistoryService;

    @Autowired
    private UserService userService;

    @Autowired
    private  ScBaseCvTankvolumeService scBaseCvTankvolumeService;

    @Autowired
    private ScPriceconfOcService scPriceconfOcService;

    @Autowired
    private DWaybillViewMapper dWaybillViewMapper;

    @Autowired
    private DWaybillAttachMapper dWaybillAttachMapper;

    @Autowired
    private TmsQueueService tmsQueueService;

    @Autowired
    @Lazy
    private TmsOrderService tmsOrderService;

    @Autowired
    private DWaybillStatusHistoryService dWaybillStatusHistoryService;

    @Autowired
    private DAccidentMapper dAccidentMapper;

    @Autowired
    private DWaybillOilPriceService dWaybillOilPriceService;

    @Autowired
    private CAccntBalanceService cAccntBalanceService;

    @Autowired
    private DUserPositionMapper dUserPositionMapper;

    @Autowired
    private SUserDevicesMapper sUserDevicesMapper;

    @Autowired
    private JPushService jPushService;

    @Autowired
    private DNoticeViewMapper dNoticeViewMapper;

    @Autowired
    private SUserMapper sUserMapper;

    @Autowired
    private DUserService dUserService;

    @Autowired
    private DUserExtService dUserExtService;

    @Autowired
    private DUserLicenseService dUserLicenseService;

    @Autowired
    private DriverCompareService driverCompareService;

    private static final String ZL_DRIVER_PREFIX = "ZHC";

    @Autowired
    private DWaybillFeeService dWaybillFeeService;

    @Autowired
    private DCompareFaceResultService dCompareFaceResultService;

    @Autowired
    private DWaybillAbandonedLogService dWaybillAbandonedLogService;

    @Autowired
    private TmsDDeliveryAttachMapper tmsDDeliveryAttachMapper;

    @Autowired
    private TmsDDeliveryMapper tmsDDeliveryMapper;

    @Autowired
    private DUserViewMapper dUserViewMapper;

    @Autowired
    private DVcstyleLicenseMapper dVcstyleLicenseMapper;

    @Autowired
    private DUserLicenseMapper dUserLicenseMapper;

    @Autowired
    private DVehicleClassifyService dVehicleClassifyService;    
    
    @Autowired
    private DFuelTypeMapper dFuelTypeMapper;

    @Autowired
    private SUserStatusMapper sUserStatusMapper;

    @Override
    public DWaybill addByTmsOrder(TmsOrder tmsOrder) throws Exception {
        LOGGER.info("DWaybillServiceImpl.addByTmsOrder param : {}", tmsOrder);

        if (null == tmsOrder) {
            LOGGER.error("DWaybillServiceImpl.addByTmsOrder param tmsOrder must not be null");
            throw new IllegalArgumentException("TMS订单不能为空");
        }

        DWaybill waybill = null;

        //根据TMS订单操作状态区分运单操作逻辑
        Integer opration = tmsOrder.getOpration();

        switch (opration) {
            case 10:

                //新增运单并发布
                waybill = this.saveAndPublishWaybill(tmsOrder);
                break;
            case 20:

                //暂挂订单
                waybill = this.pauseWaybill(tmsOrder.getIlineid());
                break;
            case 30:

                //取消订单
                waybill = this.cancelWaybill(tmsOrder.getIlineid());
                break;

            default:

                //若状态都不匹配，则默认保存
                this.saveWaybill(tmsOrder);
        }


        return waybill;
    }

    /**
     * 保存运单
     *
     * @param tmsOrder
     * @return
     */
    private Long saveWaybill(TmsOrder tmsOrder) throws Exception {
        LOGGER.info("DWaybillServiceImpl.saveWaybill param : {}", tmsOrder);

        //保存运单
        Long waybillId;

        DWaybill waybill = this.buildDWaybill(tmsOrder);

        waybillId = waybill.getId();

        //保存运单操作状态变更记录
        dWaybillStatusHistoryService.add(waybillId, DWaybillStatusTypeEnum.OPERATION.getText(),
                DWaybillOperationStatusEnum.SAVE.getText(), null, 0L, "system");
        //保存运单流程状态变更记录
        dWaybillStatusHistoryService.add(waybillId, DWaybillStatusTypeEnum.PROCESS.getText(),
                DWaybillStatusEnum.SAVE.getText(), null, 0L, "system");

        //保存运单车辆信息
        DWaybillVehicle vehicle = this.buildDWaybillVehicle(waybill, tmsOrder);

        //保存运单收货人信息
        this.buildDWaybillReceiver(waybillId, tmsOrder);

        //保存运单油价信息
//        this.buildDWaybillOilPrice(waybillId);

        //计算保存运单价格信息
        this.addDWaybillCost(DWaybillFeeDetailCostTypeEnum.CREATE_COST, waybill);

        return waybillId;
    }

    /**
     * 保存运单油价信息
     *
     * @param waybillId
     */
    private void buildDWaybillOilPrice(Long waybillId) throws Exception {
        LOGGER.info("buildDWaybillOilPrice param : {}", waybillId);

        DWaybillOilPrice oilPrice = new DWaybillOilPrice();
        oilPrice.setWaybillId(waybillId);
//        oilPrice.setDriverOilarPrice(orderCostTo.getOilarprice());
//        oilPrice.setPetrolStationOilarPrice(orderCostTo.getOilapprice());
//        oilPrice.setMarketOilPrice(orderCostTo.getMarketprice());
        dWaybillOilPriceService.add(oilPrice);
    }

    /**
     * 保存运单收货人信息
     *
     * @param waybillId
     * @param tmsOrder
     */
    private void buildDWaybillReceiver(Long waybillId, TmsOrder tmsOrder) throws Exception {
        LOGGER.info("buildDWaybillReceiver params : {}, {}", waybillId, tmsOrder);

        DWaybillReceiver receiver = new DWaybillReceiver();
        receiver.setWaybillId(waybillId);
        receiver.setReceiverName(tmsOrder.getVccontact());
        receiver.setReceiverPhone(tmsOrder.getVctel());
        receiver.setReceiverMobile(tmsOrder.getVcmobile());
        receiver.setReceiverAddress(tmsOrder.getVcaddress());
        dWaybillReceiverService.add(receiver);
    }

    /**
     * 保存运单车辆信息
     *
     * @param waybill
     * @param tmsOrder
     */
    private DWaybillVehicle buildDWaybillVehicle(DWaybill waybill, TmsOrder tmsOrder) throws Exception {
        LOGGER.info("buildDWaybillVehicle params : {}, {}", waybill, tmsOrder);

        DWaybillVehicle vehicle = new DWaybillVehicle();
        vehicle.setWaybillId(waybill.getId());
        vehicle.setVehicleTypeId(bVehicleTypeService.getIdByConditions(tmsOrder.getVcstyleno(), tmsOrder.getVcstylename(), tmsOrder.getVehicledesc()));
        vehicle.setVehicleTypeCode(tmsOrder.getVcstyleno());
        vehicle.setVehicleTypeName(tmsOrder.getVcstylename());
        vehicle.setVehicleVin(tmsOrder.getVcvin());
        vehicle.setVehicleDesc(tmsOrder.getVehicledesc());
        vehicle.setVehicleNum(tmsOrder.getDcqty());
        vehicle.setVehicleUnit(tmsOrder.getVcunit());
        vehicle.setVehicleClassifyId(waybill.getIstyleid());

//		vehicle.setTankVolume(orderCostTo.getTankvolume());//油箱容量
//		vehicle.setFuelStandard(orderCostTo.getFuelstandard());//百公里油耗

        dWaybillVehicleService.add(vehicle);

        return vehicle;
    }

    /**
     * 保存运单信息
     *
     * @param tmsOrder
     */
    private DWaybill buildDWaybill(TmsOrder tmsOrder) throws Exception {
        LOGGER.info("buildDWaybill params : {}", tmsOrder);

        //根据tmslineid判断运单是否已经存在
        DWaybill dw = this.getByTmsOrderCode(tmsOrder.getVcorderno());
        if (null != dw) {
            LOGGER.error("DWaybillServiceImpl.buildDWaybill waybill already exists");
            throw new BusinessException("运单已经存在");
        }

        DWaybill waybill = new DWaybill();
        waybill.setUserId(0L);
        waybill.setTmsOrderId(tmsOrder.getId());
        waybill.setOrderLineId(tmsOrder.getIlineid());
        waybill.setOrderCode(tmsOrder.getVcorderno());
        waybill.setOrderType(tmsOrder.getVcordertype());
        waybill.setTransportModeId(bTransportModeService.getIdByConditions(tmsOrder.getVctransno(), tmsOrder.getVctransname()));
        waybill.setTransportModeName(tmsOrder.getVctransname());
        waybill.setWithdrawWarehouseId(bWareHouseService.getIdByConditions(tmsOrder.getVcwarehouseno(), tmsOrder.getVcwarehousename(), tmsOrder.getVcwarehouseaddress(), tmsOrder.getVcstartprovince(), tmsOrder.getVcstartcity()));
        waybill.setDepartureProvince(tmsOrder.getVcstartprovince());
        waybill.setDepartureCity(tmsOrder.getVcstartcity());
        waybill.setDepartureTime(tmsOrder.getDtshipdate());
        waybill.setDealerId(bDealerService.getIdByConditions(tmsOrder.getVcdealerno(), tmsOrder.getVcdealername()));
        waybill.setDealerDistributaryId(bDealerDistributaryService.getIdByConditions(waybill.getDealerId(), tmsOrder.getVcdealerno(), tmsOrder.getVcdestname()));
        waybill.setDestProvince(tmsOrder.getVcprovincename());
        waybill.setDestCity(tmsOrder.getVccityname());
        waybill.setWaybillStatus(DWaybillStatusEnum.SAVE.getValue());
        waybill.setOperationStatus(DWaybillOperationStatusEnum.SAVE.getValue());
        waybill.setIsUrgent(tmsOrder.getIurgent() == 1 ? true : false);
        waybill.setFactoryOrderTime(tmsOrder.getDtorderdate());
        waybill.setTmsUpdateTime(tmsOrder.getDtassigndate());
        waybill.setTmsCreateTime(tmsOrder.getDtcreatedate());
        waybill.setTransportRequire(tmsOrder.getVcrequire());
        waybill.setCustomerRemark(tmsOrder.getMemo());
        waybill.setIstyleid(tmsOrder.getIstyleid());
        waybill.setWaybillType(DWaybillTypeEnum.NORMAL.getValue());


        //由知车计算出第一桶油信息，废弃掉  orderCostTo  2017-06-08 10:21:06 ligl
        //反序列化费用信息
//        OrderCostTo orderCostTo = null;
//        if (StringUtils.isNotBlank(tmsOrder.getOrdercost())) {
//            orderCostTo = JSONObject.parseObject(tmsOrder.getOrdercost().replaceAll("\"", ""), OrderCostTo.class);
//            LOGGER.info("saveWaybill orderCost : {}", orderCostTo);
//        }

        //第一桶油
//        if (null != orderCostTo) {
//            waybill.setFirstFuelTotal(orderCostTo.getFirstfueltotal());
//        }

        this.add(waybill);

        return waybill;
    }

    /**
     * 取消运单
     *
     * @param ilineid
     * @return
     */
    private DWaybill cancelWaybill(Long ilineid) throws Exception {

        return null;
    }

    /**
     * 挂起运单
     *
     * @param ilineid
     * @return
     */
    private DWaybill pauseWaybill(Long ilineid) throws Exception {

        TmsOrder tmsOrder = tmsOrderService.getTmsOrderByIlineid(ilineid);
        if (null != tmsOrder) {

        }

        return null;
    }

    /**
     * 保存后发布运单
     *
     * @param tmsOrder
     * @return
     */
    private DWaybill saveAndPublishWaybill(TmsOrder tmsOrder) throws Exception {
        LOGGER.info("DWaybillServiceImpl.saveAndPublishWaybill param : {}", tmsOrder);

        //运单保存
        Long waybillId = this.saveWaybill(tmsOrder);

        //运单发布
        DWaybill waybill = dWaybillMapper.selectByPrimaryKey(waybillId);
        waybill.setWaybillStatus(DWaybillStatusEnum.SAVE.getValue());
        dWaybillMapper.updateByPrimaryKeySelective(waybill);

        //保存运单操作状态变更记录
        dWaybillStatusHistoryService.add(waybill.getId(),
                DWaybillStatusTypeEnum.OPERATION.getText(),
                DWaybillStatusEnum.DEPARTURE.getText(),
                DWaybillOperationStatusEnum.SAVE.getText(),
                0L, "发布运单");

        return waybill;
    }

    @Override
    public DWaybill selectDwaybillByUserId(Long userId, Integer status) {
        LOGGER.info("selectDwaybillByUserId params: {} ,status {}", userId, status);
        DWaybillExample example = new DWaybillExample();
        example.createCriteria().andUserIdEqualTo(userId).andWaybillStatusEqualTo(status);
        List<DWaybill> lists = this.selectByExample(example);
        if (CollectionUtils.isNotEmpty(lists)) {
            LOGGER.info("selectDwaybillByUserId result list size : {}", lists.size());
            return lists.get(0);
        }
        return null;
    }

    @Override
    public List<DWaybill> selectDwaybillByUserId(Long userId, List<Integer> status,List<Integer> types) {
        LOGGER.info("selectDwaybillByUserId params: {} ,status {}.", userId, status);
        DWaybillExample example = new DWaybillExample();
        example.createCriteria().andUserIdEqualTo(userId).andWaybillStatusIn(status).andWaybillTypeIn(types);
        return this.selectByExample(example);
    }

    // 查询运单列表
    Map<String, Object> getList(PageVo page, List<Integer> status,int waybillType) {
        Map<String, Object> map = new HashMap<>();
        try {
            UserShowVo currentUser = userService.getCurrentUser();
            if (null == currentUser) {
                throw new BusinessException("当前登录用户不存在");
            }
            Long userId = currentUser.getId();

            Map<String, Object> paramsMap = new HashMap<>();
            paramsMap.put("userId", userId);
            String orderByClause = StringUtils.isNotBlank(page.getOrder()) == true ? page.getOrder()
                    : " dw.dispatch_time DESC";
            paramsMap.put("limitStart", page.getStartIndex());
            paramsMap.put("limitEnd", page.getPageSize());
            paramsMap.put("orderByClause", orderByClause);

            if (CollectionUtils.isNotEmpty(status)) {
                paramsMap.put("status", status);
            }
            if(waybillType>0){
                paramsMap.put("waybillType",waybillType);
            }

            page.setTotalRecord(dWaybillViewMapper.countByCondations(paramsMap));
            List<ShowOrderVo> dWaybillList = dWaybillViewMapper.getListByCondations(paramsMap);
            if (CollectionUtils.isNotEmpty(dWaybillList)) {
                dWaybillList.forEach(vo -> {
                    if (vo.getOrderTime() != null) {
                        String dt = DateUtils.getStringFromDate(vo.getOrderTime(), "yyyy-MM-dd");
                        String current = DateUtils.getStringFromDate(new Date(), "yyyy-MM-dd");
                        String time = DateUtils.getStringFromDate(vo.getOrderTime(), "yyyy-MM-dd HH:mm");
                        if (dt.equals(current)) {
                            vo.setShowWaybillDate("今日运单");
                            vo.setShowDate("今天 " + time.substring(11, 16));
                        } else {
                            vo.setShowWaybillDate(dt);
                            vo.setShowDate(dt + " " + time.substring(11, 16));
                        }
                        vo.setShowTime(time.substring(11, 16));
                    }
                    
                    // 如果是急发单显示：总价 = 总价 - 附加费
                    if (vo.getWaybillType() == 20){                    	
                        
                    	BigDecimal orderPrice = vo.getOrderPrice().subtract(vo.getExtraCost()).setScale(2);
                    	vo.setOrderPrice(orderPrice);
                    }                    
                });
            }
            map.put("page", page);
            map.put("dWaybillList", dWaybillList);
            return map;
        } catch (Exception e) {
            LOGGER.error("select current user dwaybill list error : {}.", e);
            throw new BusinessException("查询当前用户运单列表异常");
        }
    }

    @Override
    public Map<String, Object> getListByPage(PageVo page,int waybillType) throws Exception {
        return this.getList(page, null,waybillType);
    }

    @Override
    public ShowOrderVo getIntransitListByPage() throws Exception {// List<Integer>
        // statusList = new
        // ArrayList<>();
        // statusList.add(DWaybillStatusEnum.INTRANSIT.getValue());
        // statusList.add(DWaybillStatusEnum.DEAL_CAR.getValue());
        UserShowVo userVo = userService.getCurrentUser();
        // 查询运单信息
        List<Integer> statusList = new ArrayList<>();
        statusList.add(DWaybillStatusEnum.DEPARTURE.getValue());
        statusList.add(DWaybillStatusEnum.INTRANSIT.getValue());
        statusList.add(DWaybillStatusEnum.DEAL_CAR.getValue());
        ShowOrderVo sov = dWaybillViewMapper.selectOrderInfo(userVo.getId(), statusList);
        if (sov != null) {
            if (sov.getOrderTime() != null) {
                String dt = DateUtils.getStringFromDate(sov.getOrderTime(), "yyyy-MM-dd");
                String current = DateUtils.getStringFromDate(new Date(), "yyyy-MM-dd");
                String time = DateUtils.getStringFromDate(sov.getOrderTime(), "yyyy-MM-dd HH:mm");
                String string = time.substring(11, 16);
                if (dt.equals(current)) {
                    sov.setShowWaybillDate("今日运单");
                    sov.setShowDate("今天 " + string);
                } else {
                    sov.setShowWaybillDate(dt);
                    sov.setShowDate(dt + " " + string);
                }
                sov.setShowTime(string);
            }
            
            // 如果是急发单显示：总价 = 总价 - 附加费
            if (sov.getWaybillType() == 20 && null != sov.getExtraCost()){
            	BigDecimal orderPrice = sov.getOrderPrice().subtract(sov.getExtraCost()).setScale(2);
                sov.setOrderPrice(orderPrice);
            }    
        }
           
        return sov;
    }

    @Override
    public Integer confirmDliver(Long id, String attachs, UserPositionVo upv) throws Exception {
        LOGGER.info("upload confirmDliver picture params id : {}, attachs : {}.", id, attachs);
        int count = 0;
        try {
            // 查询可交车状态的运单
            DWaybillExample example = new DWaybillExample();
            example.createCriteria().andIdEqualTo(id); //.andStatusEqualTo(COrderStatusEnum.INTRANSIT.getValue());
            List<DWaybill> waybills = this.selectByExample(example);
            if (CollectionUtils.isEmpty(waybills)) {
                LOGGER.error("waybills is empty");
                throw new BusinessException("获取运单信息失败！");
            }
            DWaybill waybill = waybills.get(0);
            int lastStatus = waybill.getWaybillStatus();
            waybill.setWaybillStatus(DWaybillStatusEnum.DEAL_CAR.getValue());
            this.updateSelective(waybill);

            UserShowVo user = userService.getCurrentUser();
            if (null == user) {
                LOGGER.error("upload confirmDliver picture no user");
                throw new BusinessException("获取当前用户信息失败！");
            }
            String userName = user.getRealName();
            if (StringUtils.isEmpty(userName)) {
                userName = user.getPhone();

            }
            String attachPic = "";

            // 添加运单状态变更日志
            this.dWaybillStatusHistoryService.add(id, DWaybillStatusTypeEnum.PROCESS.getText(), DWaybillStatusEnum.getByValue(DWaybillStatusEnum.DEAL_CAR.getValue()).getText(), DWaybillStatusEnum.getByValue(lastStatus).getText(), user.getId(), userName);

            // 保存附件
            List<AttachForm> objs = JSONArray.parseArray(attachs, AttachForm.class);
            if (CollectionUtils.isNotEmpty(objs)) {
                AttachForm af;
                DWaybillAttach attach = new DWaybillAttach();
                attach.setWaybillId(id);
                attach.setUserId(user.getId());
                attach.setUserName(user.getRealName());
                attach.setCategory(AttachCategoryEnumWaybill.DELIVER.getValue());// 交车照片

                String urls = "";
                for (int i = 0; i < objs.size(); i++) {
                    af = objs.get(i);
                    attach.setPicKey(af.getImage());
                    if (StringUtils.isEmpty(urls)) {
                        urls = urls.concat(QiniuUtils.generateDownloadTicket(attach.getPicKey(), ""));
                    } else {
                        urls = urls.concat(",").concat(QiniuUtils.generateDownloadTicket(attach.getPicKey(), ""));
                    }
                    AttachTypeEnum typeEnum = AttachTypeEnum.getByValue(af.getType());
                    if (typeEnum == null) {
                        LOGGER.error("typeEnum is null");
                        throw new BusinessException("图片类型错误!");
                    }
                    attach.setType(typeEnum.getValue());
                    if ("3030".equals(attach.getType()) || attach.getType() == 3030) {
                        attachPic = QiniuUtils.generateDownloadTicket(attach.getPicKey(), "");
                    }
                    // 照片去重

                    DWaybillAttachExample attachExample = new DWaybillAttachExample();
                    attachExample.createCriteria().andWaybillIdEqualTo(id).andCategoryEqualTo(AttachCategoryEnumWaybill.DELIVER.getValue()).andTypeEqualTo(typeEnum.getValue());
                    List<DWaybillAttach> attachlist = dWaybillAttachMapper.selectByExample(attachExample);
                    if (CollectionUtils.isEmpty(attachlist)) {
                        count += dWaybillAttachMapper.insertSelective(attach);
                    } else {
                        Long oldId = attachlist.get(0).getId();
                        attach.setId(oldId);
                        count += dWaybillAttachMapper.updateByPrimaryKeySelective(attach);
                    }
                }
                if (count > 0) {
                    // 进行照片比对，判断是否是司机本人上传照片
                    //this.CompareFace(user, id, attachPic);
                    //LOGGER.info("compareFace user:{},waybillId:{},attachPic:{}", user, id, attachPic);
                    // 运单到达了要调用这个接口 推送订单到达信息到TMS系统中
                    boolean pushMessageFlag = this.pushMessage(upv, user, waybill.getOrderCode(), waybill.getOrderLineId(), urls);
                    LOGGER.info("upload confirmDliver picture zl interface error waybillid : {}, params upv:{}, user:{}, waybillCode:{}, orderLindId:{}, urls:{}.", id, upv, user, waybill.getOrderCode(), waybill.getOrderLineId(), urls);
                    if (!pushMessageFlag) {
                        LOGGER.info("upload confirmDliver picture zl interface error waybillid : {}, result : {}.", id, pushMessageFlag);
                        // throw new BusinessException("确认交车,中联接口调用失败");
                    }
                }
            }
        } catch (Exception e) {
            LOGGER.error("upload confirmDliver picture error : {}.", e);
            throw new BusinessException("上传交车照片异常");
        }
        return count;
    }

    /**
     * 人送业务交车确认接口(新)实现（司机用）
     *
     * @param id
     * @param upv
     * @param attachs
     * @return count
     * @throws Exception
     */
    @Override
    public int deliveryConfirm(Long id, UserPositionVo upv, String attachs) throws Exception {
        LOGGER.info("upload confirmDliver picture params id : {}, attachs : {}.", id, attachs);
        //交车信息
        TmsDDelivery tmsDDelivery  = new TmsDDelivery();
        // 查询可交车状态的运单
        DWaybillExample example = new DWaybillExample();
        example.createCriteria().andIdEqualTo(id); //.andStatusEqualTo(COrderStatusEnum.INTRANSIT.getValue());
        List<DWaybill> waybills = this.selectByExample(example);
        if (CollectionUtils.isEmpty(waybills)) {
            LOGGER.error("waybills is empty");
            throw new BusinessException("获取运单信息失败！");
        }
        DWaybill waybill = waybills.get(0);
        //获取之前的运单状态
        int lastStatus = waybill.getWaybillStatus();
        // 2017-4-23 候建慧 增加判断是否重复交车
        if (DWaybillStatusEnum.DEAL_CAR.getValue() == lastStatus) {
            LOGGER.info("DWaybillServiceImpl.deliveryConfirm Repeat submit it for information");
            throw new BusinessException("禁止重复提交交车信息");
        }
        //更改运单状态，改为"已交车"
        waybill.setWaybillStatus(DWaybillStatusEnum.DEAL_CAR.getValue());
        this.updateSelective(waybill);
        //获取当前登录app的司机信息
        UserShowVo user = userService.getCurrentUser();
        if (null == user) {
            LOGGER.error("delivery audit user is null");
            throw new BusinessException("获取交车审核用户信息失败！");
        }
        String userName = user.getRealName();
        if (StringUtils.isEmpty(userName)) {
            userName = user.getPhone();
        }
        // 添加运单状态变更日志
        this.dWaybillStatusHistoryService.add(id, DWaybillStatusTypeEnum.PROCESS.getText(), DWaybillStatusEnum.getByValue(DWaybillStatusEnum.DEAL_CAR.getValue()).getText(), DWaybillStatusEnum.getByValue(lastStatus).getText(), user.getId(), userName);
        //  生成交车信息并持久化
        tmsDDelivery.setWaybillId(waybill.getId());
        tmsDDelivery.setDriverId(user.getId());
        tmsDDelivery.setDeliveryLocationX(upv.getLatitude());
        tmsDDelivery.setDeliveryLocationY(upv.getLongitude());
        tmsDDelivery.setDeliveryAddr(upv.getAddress());
        tmsDDeliveryMapper.insertSelective(tmsDDelivery);
        // 写入运单的交车附件
        String urls = this.postDeliveryAttachment(tmsDDelivery, waybill, attachs);
        //推送交车信息给老tms系统
        this.pushDeliveryInfoToTMS(upv, user, waybill, urls);
        return 1;
    }

    /**
     * 写入运单的交车附件
     *
     * @param attachments
     * @return urls
     */
    public String postDeliveryAttachment(TmsDDelivery tmsDDelivery, DWaybill waybill, String attachments) {
        String urls = "";
        List<AttachForm> objs = JSONArray.parseArray(attachments, AttachForm.class);
        if (CollectionUtils.isNotEmpty(objs)) {
            AttachForm af;
            TmsDDeliveryAttach attach = new TmsDDeliveryAttach();
            attach.setWaybillId(waybill.getId());
            attach.setDeliveryId(tmsDDelivery.getId());
            for (int i = 0; i < objs.size(); i++) {
                af = objs.get(i);
                attach.setAttachKey(af.getImage());
                attach.setCategory(af.getType());
                if (StringUtils.isEmpty(urls)) {
                    urls = urls.concat(QiniuUtils.generateDownloadTicket(af.getImage(), ""));
                } else {
                    urls = urls.concat(",").concat(QiniuUtils.generateDownloadTicket(af.getImage(), ""));
                }
                // 照片去重
                TmsDDeliveryAttachExample attachExample = new TmsDDeliveryAttachExample();
                attachExample.createCriteria().andWaybillIdEqualTo(waybill.getId()).andDeliveryIdEqualTo(tmsDDelivery.getId()).andCategoryEqualTo(attach.getCategory());
                List<TmsDDeliveryAttach> old_attachment = tmsDDeliveryAttachMapper.selectByExample(attachExample);
                if (CollectionUtils.isEmpty(old_attachment)) {
                    tmsDDeliveryAttachMapper.insertSelective(attach);
                } else {
                    attach.setId(old_attachment.get(0).getId());
                    tmsDDeliveryAttachMapper.updateByPrimaryKeySelective(attach);
                }
            }
        }
        return urls;
    }

    /**
     * 推送交车信息给老TMS系统
     */
    private void pushDeliveryInfoToTMS(UserPositionVo upv, UserShowVo user, DWaybill waybill, String urls) throws Exception {
        // 运单交车调用这个接口 推送交车信息到老TMS系统中
        boolean pushMessageFlag = this.pushMessage(upv, user, waybill.getOrderCode(), waybill.getOrderLineId(), urls);
        LOGGER.info("upload confirmDliver picture zl interface error waybillid : {}, params upv:{}, user:{}, waybillCode:{}, orderLindId:{}, urls:{}.", waybill.getId(), upv, user, waybill.getOrderCode(), waybill.getOrderLineId(), urls);
        if (!pushMessageFlag) {
            LOGGER.info("upload confirmDliver picture zl interface error waybillid : {}, result : {}.", waybill.getId(), pushMessageFlag);
            // throw new BusinessException("确认交车,中联接口调用失败");
        }
    }


    // 运单到达了要调用这个接口 推送订单到达信息到TMS系统中
    private boolean pushMessage(UserPositionVo upv, UserShowVo user, String orderCode, Long orderLineId, String attachs) throws Exception {
        LOGGER.info("confirm jiaoche pic zl pushMessage params upv:{}, user:{}, orderCode:{}, orderLineId:{}, attachs:{}.", upv, user, orderCode, orderLineId, attachs);

        OrderArrivalInfo arrivalInfo = new OrderArrivalInfo();
        if (null != upv) {
            // 添加position 数据
            if (null != upv.getLatitude() && null != upv.getLongitude() && StringUtils.isNotEmpty(upv.getAddress())) {
                userService.addUserPosition(upv);
            }
            arrivalInfo.setProvince(upv.getProvince()); // 省
            arrivalInfo.setCity(upv.getCity()); // 市
            arrivalInfo.setCounty(upv.getCounty()); // 区县
            arrivalInfo.setLongitude(upv.getLatitude()); // 经度
            arrivalInfo.setLatitude(upv.getLongitude()); // 纬度
            arrivalInfo.setAddress(upv.getAddress()); // 地址
        }

        //  获取d用户
        DUser dUser = dUserService.selectByPhone(user.getPhone());
        if (null == dUser) {
            LOGGER.error("DWaybillServiceImpl.pushMessage dUser must not be null");
            throw new BusinessException(TmsDispatchOptionCodeEnum.DRIVER_INFO_SYSTEM_ERROR.getValue() + "", TmsDispatchOptionCodeEnum.DRIVER_INFO_SYSTEM_ERROR.getText());
        }

        DUserExt dUserExt = dUserExtService.selectByUserId(dUser.getId());
        if (null == dUserExt) {
            LOGGER.error("DWaybillServiceImpl.pushMessage dUserExt must not be null");
            throw new BusinessException(TmsDispatchOptionCodeEnum.DRIVER_INFO_SYSTEM_ERROR.getValue() + "", TmsDispatchOptionCodeEnum.DRIVER_INFO_SYSTEM_ERROR.getText());
        }

        arrivalInfo.setVccard(dUserExt.getIdNo()); // 身份证号
        arrivalInfo.setVcdriverno("ZHC" + dUserExt.getUserId()); // 司机编号
        arrivalInfo.setVcorderno(orderCode); // TMS系统订单编号
        arrivalInfo.setOrderilineid(orderLineId); // TMS系统订单流
        arrivalInfo.setVcname(user.getRealName()); // 司机姓名
        arrivalInfo.setPhotos(attachs); // 照片信息

        arrivalInfo.setArrivaltime(new Date()); // 到达时间
        LOGGER.info(
                "confirm jiaoche pic zl pushMessage params upv:{}, user:{}, orderCode:{}, orderLineId:{}, attachs:{}, arrivalInfo:{}.",
                upv, user, orderCode, orderLineId, attachs, arrivalInfo);

        //推送订单到达信息
        String data = this.pushOrderArrivalInfo(arrivalInfo);
        if (null != data) {
            JSONObject result = JSONObject.parseObject(data);
            if (result.getBooleanValue("success")) {
                LOGGER.info("------success-------调用中联接口订单到达成功------------- 数据结果集: {}", data);
                return true;
            }
        }
        LOGGER.info("-------error------调用中联接口订单到达失败--------------- 数据结果集: {}", data);
        // 中联结果分析处理-----结束----
        return false;
    }

    /**
     * 司机交车照片比对
     *
     * @param user
     * @param waybillId
     * @param attachPic
     */
    private void CompareFace(UserShowVo user, Long waybillId, String attachPic) throws Exception {
        DCompareFaceResult result = new DCompareFaceResult();

        //  获取d用户
        DUser dUser = dUserService.selectByPhone(user.getPhone());
        if (null == dUser) {
            LOGGER.error("DWaybillServiceImpl.CompareFace dUser must not be null");
            throw new BusinessException(TmsDispatchOptionCodeEnum.DRIVER_INFO_SYSTEM_ERROR.getValue() + "", TmsDispatchOptionCodeEnum.DRIVER_INFO_SYSTEM_ERROR.getText());
        }

        DUserExt dUserExt = dUserExtService.selectByUserId(dUser.getId());
        if (null == dUserExt) {
            LOGGER.error("DWaybillServiceImpl.CompareFace dUserExt must not be null");
            throw new BusinessException(TmsDispatchOptionCodeEnum.DRIVER_INFO_SYSTEM_ERROR.getValue() + "", TmsDispatchOptionCodeEnum.DRIVER_INFO_SYSTEM_ERROR.getText());
        }

        String userPic = dUserExt.getImage();

        userPic = QiniuUtils.generateDownloadTicket(userPic, "");
        if (StringUtils.isBlank(userPic)) {
            result.setMsgCode("600");
            result.setErrorMsg("获取需要比对的图片失败");
            result.setIsSelf(false);
        }
        if (StringUtils.isBlank(attachPic)) {
            result.setMsgCode("700");
            result.setErrorMsg("获取比对图片失败");
            result.setIsSelf(false);
        } else {
            result = driverCompareService.compareFaceApi(userPic, attachPic);
            LOGGER.info("dwaybillService compareFace  params userPic:{},attachPic:{}", userPic, attachPic);
        }

        DCompareFaceResultExample example = new DCompareFaceResultExample();
        example.createCriteria().andWaybillIdEqualTo(waybillId).andIsFirstUploadEqualTo(true);
        List<DCompareFaceResult> list = dCompareFaceResultService.selectByExample(example);
        Boolean isFirstUpload = false;
        if (CollectionUtils.isEmpty(list)) {
            isFirstUpload = true;

        }
        result.setUserId(user.getId());
        result.setWaybillId(waybillId);
        result.setIsFirstUpload(isFirstUpload);
        dCompareFaceResultService.add(result);
        LOGGER.info("CompareFace result: isSelf:{},msgCode:{},errorMsg:{}", result.getIsSelf(), result.getMsgCode(), result.getErrorMsg());

    }


    @Override
    public DWaybillDetailVo getById(long id) throws Exception {
        LOGGER.info("select dwaybill details params id : {}.", id);
        try {

            DWaybillDetailVo dWaybillDetailVo = dWaybillViewMapper.getDetailsById(id);
            if (null == dWaybillDetailVo) {
                return new DWaybillDetailVo();
            }

            Long user_id = dWaybillMapper.selectByPrimaryKey(id).getUserId();
            SUser user = sUserMapper.selectByPrimaryKey(user_id);

            List<DUserVo> duserlist = dUserViewMapper.selectByCondition(user.getPhone());
            if (CollectionUtils.isNotEmpty(duserlist)) {
                DUserVo dUserVo = duserlist.get(0);
                if (StringUtils.isNotBlank(dUserVo.getImage())) {
                    String treatMethod = "?imageView2/1/w/220/h/240";
                    dWaybillDetailVo.setDriverAvatarKey(QiniuUtils.generateDownloadTicket(dUserVo.getImage(), treatMethod));
                }
            }

            List<DeliveryAttachVo> deliverPics = dWaybillDetailVo.getDeliverPics();
            List<DeliveryAttachVo> deliveryAttachVoList = new ArrayList<>();

            // 交车照片
            if (CollectionUtils.isNotEmpty(deliverPics)) {
                DeliveryAttachVo deliveryAttach = null;
                for (int i = 0; i < deliverPics.size(); i++) {
                    deliveryAttach = deliverPics.get(i);
                    deliveryAttach.setPicKey(QiniuUtils.generateDownloadTicket(deliveryAttach.getAttachKey(), ""));
                    deliveryAttach.setCategory_desc(AttachTypeEnum.getByValue(deliveryAttach.getType()).getText());
                    deliveryAttachVoList.add(deliveryAttach);
                }
            }

            // 带伤照片
            List<AttachVo> damagePics = dWaybillDetailVo.getDamageAttach();
            if (CollectionUtils.isNotEmpty(damagePics)) {
                damagePics.stream().filter((item) -> !"".equals(item.getPicKey())).forEach(item -> {
                    item.setPicKey(QiniuUtils.generateDownloadTicket(item.getPicKey(), ""));
                });
            }

            // 事故申报照片
            List<AttachVo> accidentPics = dWaybillDetailVo.getAccidentPics();
            if (CollectionUtils.isNotEmpty(accidentPics)) {
                accidentPics.stream().filter((accident) -> !"".equals(accident.getPicKey())).forEach(accident -> {
                    accident.setPicKey(QiniuUtils.generateDownloadTicket(accident.getPicKey(), ""));
                });
            }

            dWaybillDetailVo.setFees(this.buildFees(dWaybillDetailVo));
            if (null == dWaybillDetailVo.getShippingFee() || (1 != dWaybillDetailVo.getShippingFee().compareTo(BigDecimal.ZERO))) {
                dWaybillDetailVo.setShippingFee(dWaybillDetailVo.getOrderPrice());
            }

            // 添加照片定位地址
            //@TODO 所有运单明细的查询都调用这一个接口，所以只能在此做判断，下一步要把不同运单状态的查询接口区分开来
            if(!Objects.equals(dWaybillDetailVo.getDeliveryID(),null)) {
                dWaybillDetailVo.setPhotoAdderss(tmsDDeliveryMapper.selectByPrimaryKey(dWaybillDetailVo.getDeliveryID()).getDeliveryAddr());
            }//如果该条运单有交车信息(deliveryid),则将delivery中的交车地址回写到运单上

            dWaybillDetailVo.setDeliverPics(deliveryAttachVoList); //交车照片写入运单明细vo

            return dWaybillDetailVo;
        } catch (Exception e) {
            LOGGER.error("select dwaybill deatils params id : {}, error : {}.", id, e);
            throw new BusinessException("查询运单明细异常");
        }
    }

    private List<DWaybillFeeVo> buildFees(DWaybillDetailVo dWaybillDetailVo) throws Exception {
        List<DWaybillFeeVo> fees = new ArrayList<>();

//        List<DWaybillFeeDetail> list = dWaybillFeeDetailService.getListByWaybillId(dWaybillDetailVo.getId());

//        if ( CollectionUtils.isNotEmpty(list) ) {
//            list.stream().forEach( f -> {
//                DWaybillFeeVo vo = new DWaybillFeeVo();
//                vo.setItem(f.getFeeName());
//                vo.setValue(f.getCost() == null ? "0.00" : f.getCost()+"");
//                vo.setText("¥");
//                fees.add(vo);
//            } );
//        }

//        DWaybillFeeVo sc = new DWaybillFeeVo();
//        sc.setItem("运费");
//        sc.setValue( null != dWaybillDetailVo.getShippingFee() ? dWaybillDetailVo.getShippingFee() + "" : "0.00" );
//        sc.setText("¥" + sc.getValue());
//        fees.add(sc);

        DWaybillFeeVo ffm = new DWaybillFeeVo();
        ffm.setItem("第一箱油油量");
        ffm.setValue(null != dWaybillDetailVo.getFirstFuelTotal() ? dWaybillDetailVo.getFirstFuelTotal() + "" : "0.00");
        ffm.setText(ffm.getValue() + "L");
        fees.add(ffm);

        DWaybillFeeVo cra = new DWaybillFeeVo();
        cra.setItem("油卡充值金额");
        cra.setValue(null != dWaybillDetailVo.getRemainingOilFee() ? dWaybillDetailVo.getRemainingOilFee() + "" : "0.00");
        cra.setText("¥" + cra.getValue());
        fees.add(cra);

        DWaybillFeeVo crm = new DWaybillFeeVo();
        crm.setItem("油卡充值油量");
        crm.setValue(null != dWaybillDetailVo.getRemainingOilFee() ?
                dWaybillDetailVo.getRemainingOilFee().divide(dWaybillDetailVo.getOilPercent(), 2, RoundingMode.HALF_UP) + ""
                : "0.00");
        crm.setText(crm.getValue() + "L");
        fees.add(crm);

        DWaybillFeeVo op = new DWaybillFeeVo();
        op.setItem("油价");
        op.setValue(null != dWaybillDetailVo.getOilPercent() ? dWaybillDetailVo.getOilPercent() + "" : "0.00");
        op.setText(op.getValue() + "¥/L");
        fees.add(op);

        DWaybillFeeVo tfc = new DWaybillFeeVo();
        tfc.setItem("总油费");
        tfc.setValue(null != dWaybillDetailVo.getFuelCost() ? dWaybillDetailVo.getFuelCost() + "" : "0.00");
        tfc.setText("¥" + tfc.getValue());
        fees.add(tfc);

        // 附加费
        DWaybillFeeVo ef = new DWaybillFeeVo();
        ef.setItem("附加费");
        ef.setValue(null != dWaybillDetailVo.getExtraCost() ? dWaybillDetailVo.getExtraCost() + "" : "0.00");
        ef.setText("¥" + ef.getValue());
        fees.add(ef);
        
        //计算油卡充值油量
        DWaybillFeeVo tf = new DWaybillFeeVo();
        tf.setItem("总运费");
        tf.setValue(null != dWaybillDetailVo.getOrderPrice() ? dWaybillDetailVo.getOrderPrice() + "" : "0.00");
        tf.setText("¥" + tf.getValue());
        fees.add(tf);
        
        return fees;

        /** DWaybillFeeVo total = new DWaybillFeeVo();
         total.setItem("合计");
         total.setValue(dWaybillDetailVo.getOrderPrice()==null?"0:00":dWaybillDetailVo.getOrderPrice().toString());
         fees.add(total); */

        /** DWaybillFeeVo shippingFee = new DWaybillFeeVo();
         shippingFee.setItem("运费");
         shippingFee.setValue(dWaybillDetailVo.getShippingFee()==null?"0:00":dWaybillDetailVo.getShippingFee().toString());
         shippingFee.setText("¥" + dWaybillDetailVo.getShippingFee()==null?"0:00":dWaybillDetailVo.getShippingFee().toString());
         fees.add(shippingFee); */
//        try {
//            DWaybillFeeVo fuelCost = new DWaybillFeeVo();
//            fuelCost.setItem("总油费");
//            fuelCost.setValue(dWaybillDetailVo.getFuelCost() == null ? "0.00" : dWaybillDetailVo.getFuelCost().toString());
//            fuelCost.setText("¥" + fuelCost.getValue());
//            fees.add(fuelCost);
//
//            DWaybillFeeVo fuelConsumption = new DWaybillFeeVo();
//            fuelConsumption.setItem("油量");
//            fuelConsumption.setValue(dWaybillDetailVo.getFuelConsumption() == null ? "0.00" : dWaybillDetailVo.getFuelConsumption().toString());
//            fuelConsumption.setText(fuelConsumption.getValue() + "L");
//            fees.add(fuelConsumption);
//
//            DWaybillFeeVo oilPrice = new DWaybillFeeVo();
//            oilPrice.setItem("油价");
//            oilPrice.setValue(dWaybillDetailVo.getOilPrice() == null ? "0.00" : dWaybillDetailVo.getOilPrice().toString());
//            oilPrice.setText(oilPrice.getValue() + "¥/L");
//            fees.add(oilPrice);
//
//            return fees;
//        } catch (Exception e) {
//            LOGGER.error("select fees error : {}.", e);
//            throw new BusinessException("查询运单费用明细异常");
//        }
    }

    @Override
    public Map<String, Object> getDoneByPage(PageVo page) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            UserShowVo currentUser = userService.getCurrentUser();
            if (null == currentUser) {
                throw new BusinessException("当前登录用户不存在");
            }
            Long userId = currentUser.getId();

            Map<String, Object> paramsMap = new HashMap<>();
            paramsMap.put("userId", userId);
            String orderByClause = StringUtils.isNotBlank(page.getOrder()) == true ? page.getOrder()
                    : " dw.id";
            paramsMap.put("limitStart", page.getStartIndex());
            paramsMap.put("limitEnd", page.getPageSize());
            paramsMap.put("orderByClause", orderByClause);

            List<Integer> statusList = new ArrayList<>();
            statusList.add(DWaybillStatusEnum.COMPLETED.getValue());

            if (CollectionUtils.isNotEmpty(statusList)) {
                paramsMap.put("status", statusList);
            }

            page.setTotalRecord(dWaybillViewMapper.countDoneList(paramsMap));
            List<DWaybillDoneVo> list = dWaybillViewMapper.getDoneList(paramsMap);

            List<Map<String, Object>> mapList = new ArrayList<>();
            for (DWaybillDoneVo dWaybillDoneVo : list) {
                Date orderTime = dWaybillDoneVo.getOrderTime();
                Calendar ca = Calendar.getInstance();
                ca.setTime(orderTime);
                int month = ca.get(Calendar.MONTH) + 1;

                List<String> months = new ArrayList<>();
                for (Map<String, Object> map2 : mapList) {
                    String oldMonth = (String) map2.get("month");
                    months.add(oldMonth);
                }

                if (months.contains(ca.get(Calendar.YEAR) + "年" + month + "月")) {
                    for (Map<String, Object> map2 : mapList) {
                        String oldMonth = (String) map2.get("month");

                        if (oldMonth.equals(ca.get(Calendar.YEAR) + "年" + month + "月")) {
                            @SuppressWarnings("unchecked")
                            List<DWaybillDoneVo> waybills = (List<DWaybillDoneVo>) map2.get("waybills");
                            waybills.add(dWaybillDoneVo);
                        }
                    }
                } else {
                    Map<String, Object> map = new HashMap<>();
                    List<DWaybillDoneVo> newList = new ArrayList<>();
                    newList.add(dWaybillDoneVo);
                    map.put("month", ca.get(Calendar.YEAR) + "年" + month + "月");
                    map.put("waybills", newList);

                    mapList.add(map);
                }
            }

            resultMap.put("page", page);
            resultMap.put("list", mapList);

            return resultMap;
        } catch (Exception e) {
            LOGGER.error("select user done dwaybill error : {}.", e);
            throw new BusinessException("查询出车记录异常");
        }
    }

    @Override
    public DWaybill getCompletedByTmsIlineid(Long ilineid) {
        LOGGER.info("getByTmsIlineid param : {}", ilineid);
        if (null == ilineid) {
            LOGGER.error("getByTmsIlineid param ilineid must not be null");
            throw new IllegalArgumentException("订单流水号");
        }

        DWaybillExample example = new DWaybillExample();
        // 查询 为完成的运单 更新回单价格
        List<Integer> dWaybillStatusList = new ArrayList<>();
        // dWaybillStatusList.add(DWaybillStatusEnum.SAVE.getValue());
        // dWaybillStatusList.add(DWaybillStatusEnum.INTRANSIT.getValue());
        dWaybillStatusList.add(DWaybillStatusEnum.DEAL_CAR.getValue());
        dWaybillStatusList.add(DWaybillStatusEnum.EXCEPTION_CONFIRM.getValue());
        dWaybillStatusList.add(DWaybillStatusEnum.COMPLETED.getValue());

        example.createCriteria().andOrderLineIdEqualTo(ilineid).andWaybillStatusIn(dWaybillStatusList);

        List<DWaybill> list = dWaybillMapper.selectByExample(example);
        LOGGER.info("getByTmsIlineid list: {}", JSONObject.toJSONString(list));
        if (CollectionUtils.isNotEmpty(list)) {
            return list.get(0);
//            LOGGER.error("getByTmsIlineid list must not empty");
//            throw new BusinessException("查询运单信息失败");
        }

        return null;
    }

    @Override
    public BigDecimal computeOrderCost(String orderCost, boolean isUpdate, Long waybillId) {
        LOGGER.info("computeOrderCost params : {}, {}, {}", orderCost, isUpdate, waybillId);

        //新增时订单价格不能为空，但是回单时可以为空
        if (!isUpdate) {
            if (StringUtils.isBlank(orderCost)) {
                LOGGER.error("computeOrderCost param orderCost must not be null");
                throw new IllegalArgumentException("订单价格不能为空");
            }
        }

        //总价格
        BigDecimal totalCost = BigDecimal.ZERO.setScale(2);

        if (StringUtils.isNotBlank(orderCost)) {
            //解析价格
            JSONObject objects = JSONObject.parseObject(orderCost);
            BigDecimal km = objects.getBigDecimal("'km'");
            BigDecimal price = objects.getBigDecimal("'price'");
            objects.remove("'km'");
            objects.remove("'price'");
            if (null != km && null != price) {
                objects.putIfAbsent("基础运费", km.multiply(price));
            }

            Set<Map.Entry<String, Object>> set = objects.entrySet();
            Iterator<Map.Entry<String, Object>> iterator = set.iterator();
            while (iterator.hasNext()) {
                Map.Entry<String, Object> next = iterator.next();
                String key = next.getKey();
                if (key.startsWith("'")) {
                    key = key.substring(1, key.length());
                }
                if (key.endsWith("'")) {
                    key = key.substring(0, key.length() - 1);
                }
                BigDecimal value = new BigDecimal(next.getValue().toString());
                totalCost = totalCost.add(value);

                DWaybillFeeDetail feeDetail = new DWaybillFeeDetail();
                if (!isUpdate) {
                    feeDetail.setCostType(DWaybillFeeDetailCostTypeEnum.CREATE_COST.getText());
                } else {
                    feeDetail.setCostType(DWaybillFeeDetailCostTypeEnum.RETURN_COST.getText());
                }
                feeDetail.setWaybillId(waybillId);
                feeDetail.setFeeId(dWaybillFeeTypeService.getIdByConditions(key));
                feeDetail.setFeeName(key);
                feeDetail.setCost(value);
                dWaybillFeeDetailService.add(feeDetail);
            }

            DWaybill waybill = this.getByPrimaryId(waybillId);

            //新增时设置原价和回单价相同，回单更新时只更新确认回单价
            if (!isUpdate) {
                waybill.setOriginalTotalCost(totalCost);
                waybill.setConfirmTotalCost(totalCost);
            } else {
                if (0 != totalCost.compareTo(BigDecimal.ZERO.setScale(2))) {
                    waybill.setConfirmTotalCost(totalCost);
                }
            }

            waybill.setDistance(km);
            waybill.setPricePerKm(price);

            //计算到达时间
            if (null == waybill.getDepartureTime()) {
                DateTime departureTime = new DateTime(waybill.getDepartureTime());
                Date arrivalTime = new DateTime(departureTime.year().get(),
                        departureTime.monthOfYear().get(),
                        departureTime.getDayOfMonth(),
                        16, 0,
                        0).plusDays(km.divide(BigDecimal.valueOf(550), 0, RoundingMode.UP).intValue()).toDate();
                waybill.setArrivalTime(arrivalTime);
            }
            dWaybillMapper.updateByPrimaryKeySelective(waybill);
        }

        return totalCost;
    }

    @SuppressWarnings("unchecked")
    @Override
    public Map<String, Object> getPageInfo() {
        Map<String, Object> map = new HashMap<>();
        try {
            Result<Map<String, Object>> balances = cAccntBalanceService.getBalances();
            BigDecimal balance = (BigDecimal) balances.getData().get("balance");

            List<Integer> statuslist = new ArrayList<>();
            // statuslist.add(DWaybillStatusEnum.INTRANSIT.getValue());
            statuslist.add(DWaybillStatusEnum.COMPLETED.getValue());
            PageVo page = new PageVo();
            Map<String, Object> mapResult = this.getList(page, statuslist,0);
            List<ShowOrderVo> showOrderVoList = (List<ShowOrderVo>) mapResult.get("dWaybillList");
            if (CollectionUtils.isEmpty(showOrderVoList)) {
                map.put("doneCount", 0);
            } else {
                // map.put("doneCount", showOrderVoList.size());
                map.put("doneCount", page.getTotalRecord());
            }

            UserShowVo user = userService.getCurrentUser();
            map.put("balance", balance);
            map.put("userStauts",20);

            SUserStatusExample example = new SUserStatusExample();
            example.createCriteria().andUserIdEqualTo(user.getId());
            example.setOrderByClause("gmt_create desc");
            List<SUserStatus> list = sUserStatusMapper.selectByExample(example);
            if(CollectionUtils.isNotEmpty(list)){
                map.put("userStauts", list.get(0).getUserStatus());
            }

            ShowOrderVo showOrderVo = this.getIntransitListByPage();
            if (null != showOrderVo) {
                map.put("userStauts", 30);
            }
            map.put("showOrderVo", showOrderVo);

            //增加消息是否有未读消息
            int intHasNoRead = dNoticeViewMapper.countIsNotReadByUserID(user.getId());
            map.put("ishasNoRead", intHasNoRead);
            //急发单数量
            List<Integer> statusList = new ArrayList<>();
            statusList.add(DWaybillStatusEnum.SAVE.getValue());
            Map<String, Object> paramsMap = new HashMap<>();
            paramsMap.put("status", statusList);
            paramsMap.put("waybillType", DWaybillTypeEnum.QUICK.getValue());
            map.put("quickAmunt",this.dWaybillViewMapper.countByQuickDispatchList(paramsMap));

            return map;
        } catch (Exception e) {
            LOGGER.error("select page info error : {}.", e.getMessage());
            throw new BusinessException("查询首页信息异常");
        }
    }

    /*@Override
    public boolean dispatchDriver(Long waybillId, String phone, boolean isConsumer) {
		try {
			DWaybill dWaybill = dWaybillMapper.selectByPrimaryKey(waybillId);
			if (null != dWaybill) {
				String waybillIdStr = dWaybill.getId().toString();
				String tmsSerialNo = dWaybill.getOrderLineId().toString();
				int lastStatus = dWaybill.getWaybillStatus();
				// 已派单
				if (dWaybill.getUserId() > 0) {
					LOGGER.info("===dispatchDriver===运单已派单给其他司机=={}", dWaybill.getUserId());
					tmsQueueService.removeOrder(waybillIdStr, tmsSerialNo);
					return false;
				}
				SUser user = null;
				if (isConsumer) {
					user = userService.getByPhone(phone, Arrays.asList(UserTypeEnum.CONSUMER_DRIVER.getValue()));
				} else {
					user = userService.getByPhone(phone, Arrays.asList(UserTypeEnum.SEND_DRIVER.getValue()));
				}
				if (null == user) {
					LOGGER.info("===dispatchDriver===用户不可用=={}", phone);
					tmsQueueService.removeDriver(phone);
					return false;
				}
				Boolean tmsUserFlag = userService.isTmsUser(phone);
				if (!tmsUserFlag) {
					LOGGER.info("===dispatchDriver===用户不是人送司机=={}", phone);
					tmsQueueService.removeDriver(phone);
					return false;
				}
				// 司机是否有未完成订单判断
				DWaybillExample dwe = new DWaybillExample();
				dwe.createCriteria().andUserIdEqualTo(user.getId())
						.andWaybillStatusLessThan(DWaybillStatusEnum.COMPLETED.getValue());
				List<DWaybill> list = dWaybillMapper.selectByExample(dwe);
				if (!tmsUserFlag || list.size() > 0) {
					// 有未完成运单
					tmsQueueService.removeDriver(phone);
					return false;
				}
				dWaybill.setUserId(user.getId());
				dWaybill.setDispatchTime(new Date());
				dWaybill.setWaybillStatus(DWaybillStatusEnum.DEPARTURE.getValue()); // 待发运
				// dWaybill.setOutsetTime(new Date());
				dWaybillMapper.updateByPrimaryKeySelective(dWaybill);
				// 添加日志
				dWaybillStatusHistoryService.add(waybillId, DWaybillStatusTypeEnum.PROCESS.getText(),
						DWaybillStatusEnum.DEPARTURE.getText(), DWaybillStatusEnum.getByValue(lastStatus).getText(), 0L,
						"系统派单");
				// 异步推送派单信息和在途司机实时位置信息
				int returnFlag = this.pushMessage(dWaybill.getOrderCode(), dWaybill.getOrderLineId(), user);
				LOGGER.info("===dispatchDriver===异步推送派单信息和在途司机实时位置信息=={}", returnFlag);
				boolean rtnFlag = this.dispatchOption(returnFlag, phone, dWaybill, lastStatus, isConsumer);
				LOGGER.info("===dispatchDriver===rtnFlag=={}", rtnFlag);
				if (!rtnFlag) {
					return false;
				}
				// push消息给司机 TODO司机发短信注释
				sendMessageService.sendDispatchMessage(dWaybill.getOrderCode(), phone);
				return true;
			}
		} catch (Exception e) {
			LOGGER.error("update dwaybill userid error : {}.", e.getMessage());
			// throw new BusinessException("队列派单业务处理异常");
		}
		return false;
	}*/

    @Override
    public void dispatchDWaybill(DWaybill waybill, String userPhone, boolean isConsumer) throws Exception {
        LOGGER.info("DWaybillServiceImpl.dispatchDriver params : {}, {}, {}", waybill, userPhone, isConsumer);

        String waybillIdStr = waybill.getId().toString();

        if (null != waybill) {

            // 已派单
            if (waybill.getUserId() > 0) {
                LOGGER.info("DWaybillServiceImpl.dispatchDWaybill userId of dWaybill is not null error: {}, {}", waybill.getId(), waybill.getUserId());
                throw new BusinessException(TmsDispatchOptionCodeEnum.WAYBILL_HAS_BEEN_SENT.getValue() + "", TmsDispatchOptionCodeEnum.WAYBILL_HAS_BEEN_SENT.getText());
            }

            SUser user = null;
            if (isConsumer) {
                user = userService.getByPhone(userPhone, Arrays.asList(UserTypeEnum.CONSUMER_DRIVER.getValue()));
            } else {
                user = userService.getByPhone(userPhone, Arrays.asList(UserTypeEnum.SEND_DRIVER.getValue()));
            }

            if (null == user) {
                LOGGER.info("DWaybillServiceImpl.dispatchDWaybill user is disable", userPhone);
                throw new BusinessException(TmsDispatchOptionCodeEnum.DRIVER_IS_DISABLE.getValue() + "", TmsDispatchOptionCodeEnum.DRIVER_IS_DISABLE.getText());
            }

            /**
             * 司机是否是知车司机
             */
            Boolean tmsUserFlag = userService.isTmsUser(userPhone);
            if (!tmsUserFlag) {
                LOGGER.info("DWaybillServiceImpl.dispatchDWaybill user is not tms driver", userPhone);
                throw new BusinessException(TmsDispatchOptionCodeEnum.DRIVER_IS_NOT_TMS_DRIVER.getValue() + "", TmsDispatchOptionCodeEnum.DRIVER_IS_NOT_TMS_DRIVER.getText());
            }

            /**
             * 司机是否有未完成订单判断
             */
            if (hasIntransitDWaybillForUser(user.getId())) {
                LOGGER.error("DWaybillServiceImpl.dispatchDWaybill user already have waybill");
                throw new BusinessException(TmsDispatchOptionCodeEnum.DRIVER_ALREADY_HAVE_WAYBILL.getValue() + "", TmsDispatchOptionCodeEnum.DRIVER_ALREADY_HAVE_WAYBILL.getText());
            }

            Integer waybillStatus = waybill.getWaybillStatus();

            /**
             * 2017年06月28日10:22:43 liguanglu注掉价格计算 由自动任务计算
            //更新运单价格
            Map<Integer, Object> waybillCost = null;
            try{
                waybillCost = this.addDWaybillCost(DWaybillFeeDetailCostTypeEnum.RETURN_COST, waybill);

            }catch (Exception e){
                LOGGER.error("DWaybillServiceImpl.dispatchDWaybill clac cost failed : {}", waybill);
                if (e instanceof BusinessException) {
                    throw new BusinessException(TmsDispatchOptionCodeEnum.WAYBILL_RECALC_COST_FAILED.getValue() + "", e.getMessage());
                }
                throw new BusinessException(TmsDispatchOptionCodeEnum.WAYBILL_RECALC_COST_FAILED.getValue() + "", TmsDispatchOptionCodeEnum.WAYBILL_RECALC_COST_FAILED.getText());
            }
            */
            /**
             * 更新运单为待发运(派单成功)
             */
            try {
                this.updateIsDispatch(user.getId(), waybill.getId(), new Date(), DWaybillStatusEnum.DEPARTURE.getValue());
            } catch (Exception e) {
                LOGGER.error("DWaybillServiceImpl.dispatchDWaybill calc cost failed : {}", waybill);
                throw new BusinessException(TmsDispatchOptionCodeEnum.WAYBILL_RECALC_COST_FAILED.getValue() + "", TmsDispatchOptionCodeEnum.WAYBILL_RECALC_COST_FAILED.getText());
            }

            // 添加日志
            dWaybillStatusHistoryService.add(waybill.getId(), DWaybillStatusTypeEnum.PROCESS.getText(),
                    DWaybillStatusEnum.DEPARTURE.getText(), DWaybillStatusEnum.getByValue(waybillStatus).getText(), 0L,
                    "系统派单");

            // 异步推送派单信息和在途司机实时位置信息
//            if (null == waybillCost) {
//                LOGGER.info("dWaybillFeeService.getWaybillCostByCalc is error ", waybillCost);
//                throw new BusinessException("价格计算出错");  //待改
//            }
            int returnCode = this.pushMessage(waybill, waybill.getOrderLineId(), user);

            LOGGER.info("DWaybillServiceImpl.dispatchDWaybill pushMessage return value : {}", returnCode);

            /**
             * 解析接口返回值
             */
            this.analyzeTheReturnCode(returnCode, userPhone, waybillIdStr, waybillStatus, isConsumer);
        }
    }

    /**
     * 队列 直接给分供方司机派单
     * @param orderCodes 中联订单号
     * @param user       司机信息
     * @param isConsumer the is consumer
     * @return
     * @throws Exception
     */
    @Override
    public Result<String> dispatchConsumerDriver(String orderCodes, SUser user, boolean isConsumer) throws Exception {
        Result<String> r = new Result<>(false);
        //  非空认证
        String phone = user.getPhone();
        if (StringUtils.isBlank(orderCodes)) {
            r.setMessage("订单号不可为空");
            return r;
        }
        // 订单列表
        List<String> orderCodeList = new ArrayList<>();
        String[] orderCodeArray = orderCodes.split(",");
        for (String s : orderCodeArray) {
            orderCodeList.add(s.trim());
        }
        DWaybillExample dwe = new DWaybillExample();
        dwe.createCriteria().andUserIdEqualTo(0L).andOrderCodeIn(orderCodeList);
        List<DWaybill> dList = dWaybillMapper.selectByExample(dwe);
        if (dList.size() <= 0) {
            r.setMessage("订单数据不存在");
            return r;
        }
        List<TmsQueueOrderVo> failList = new ArrayList<>(); // 派单失败列表
        StringBuffer sb = new StringBuffer("");
        String sbStr = null;
        try {
            for (DWaybill dWaybill : dList) {
                boolean isInRedis = false;
                Long waybillId = dWaybill.getId();
                String waybillIdStr = waybillId.toString();
                String tmsSerialNo = dWaybill.getOrderLineId().toString();
                // 删除队列订单
                TmsQueueOrderVo tqo = TmsQueueApi.getOrder(waybillIdStr, tmsSerialNo);
                if (null != tqo) {
                    isInRedis = true;
                    tmsQueueService.removeOrder(waybillIdStr, tmsSerialNo);
                }
                int lastStatus = dWaybill.getWaybillStatus();
                dWaybill.setUserId(user.getId());
                dWaybill.setWaybillStatus(DWaybillStatusEnum.DEPARTURE.getValue()); // 待发车
                dWaybill.setOutsetTime(new Date());
                dWaybillMapper.updateByPrimaryKeySelective(dWaybill);
                // 添加日志
                dWaybillStatusHistoryService.add(waybillId, DWaybillStatusTypeEnum.PROCESS.getText(), DWaybillStatusEnum.DEPARTURE.getText(), DWaybillStatusEnum.getByValue(lastStatus).getText(), 0L, "系统派单");
                // 异步推送派单信息和在途司机实时位置信息
                int returnFlag = this.pushMessage(dWaybill.getOrderCode(), dWaybill.getOrderLineId(), user);
                // boolean rtnFlag = this.dispatchOption(returnFlag, phone, dWaybill, lastStatus, isConsumer);

                try {
                    this.analyzeTheReturnCode(returnFlag, phone, waybillIdStr, lastStatus, isConsumer);
                } catch (Exception e) {
                    LOGGER.error("DWaybillServiceImpl.dispatchConsumerDriver error : {}", e);
                    if (isInRedis) {
                        failList.add(tqo);
                    }
                    continue;
                }

                // push消息给司机 TODO司机发短信注释
                // sendMessageService.sendDispatchMessage(dWaybill.getOrderCode(), phone);
                sb.append(dWaybill.getOrderCode()).append(", ");
            }
            sbStr = sb.toString();
            if (sbStr.endsWith(", ")) {
                sbStr = sbStr.substring(0, sbStr.length() - 2);
                // push消息给司机 TODO司机发短信注释
                sendMessageService.sendDispatchMessage(sbStr, phone);
            }
        } catch (Exception e) {
            if (failList.size() > 0) {
                for (TmsQueueOrderVo tqov : failList) {
                    tmsQueueService.appendOrder(tqov);
                }
            }
            LOGGER.error("分供方队列派单业务处理异常 : {}.", e.getMessage());
            // throw new BusinessException("分供方队列派单业务处理异常");
        }
        r.setData(sbStr);
        r.setSuccess(true);
        return r;
    }

    /**
     * 派单解析
     *
     * @param messageCode 状态码
     * @param userPhone   手机号
     * @param waybillId   运单
     * @param lastStatus  最后状态
     * @param isConsumer  是否是分供方
     * @return 执行状态
     */
    private void analyzeTheReturnCode(int messageCode, String userPhone, String waybillId, Integer lastStatus, Boolean isConsumer) throws Exception {

        String returnMsg;

        //是否失败
        Boolean isFailed = true;

        if (messageCode == -1) {

            LOGGER.error("DWaybillServiceImpl.analyzeTheReturnCode error push dispatch message return : {}", messageCode);

            if (TmsUrlConstant.PULL_SENDMESSAGE_CONFIG) {
                if (!TmsQueueApi.isSendSystemWaringMessage()) {
                    sendMessageService.sendDispatchSystemMessage(waybillId, "15811132841");
//                    sendMessageService.sendDispatchSystemMessage(waybillId, "13681112369");
                    TmsQueueApi.addSendSystemWaringMessageFlag();

                }
            }

            throw new BusinessException(TmsDispatchOptionCodeEnum.PUSH_DISPATCH_MSG.getValue() + "", TmsDispatchOptionCodeEnum.PUSH_DISPATCH_MSG.getText());
        } else {

            returnMsg = TmsDispatchOptionCodeEnum.getByValue(messageCode).getText();

            // 成功
            if (messageCode == TmsDispatchOptionCodeEnum.OK.getValue()) {

                LOGGER.info("DWaybillServiceImpl.analyzeTheReturnCode dispatch is successful : {}, {}, {}", returnMsg, waybillId, userPhone);
                isFailed = false;

                // 司机信息错误
            } else {
                if (!isConsumer) {
                    LOGGER.info("DWaybillServiceImpl.analyzeTheReturnCode dispatch is error : {}, {}, {}", returnMsg, waybillId, userPhone);
                    throw new BusinessException(TmsDispatchOptionCodeEnum.getByValue(messageCode).getValue() + "", TmsDispatchOptionCodeEnum.getByValue(messageCode).getText());
                }
            }
        }


        if (isFailed) {

            LOGGER.error("DWaybillServiceImpl.analyzeTheReturnCode error : {}, {} ,{}", returnMsg, waybillId, userPhone);

            // 订单回滚操作
            this.resetOrderStatus(lastStatus, returnMsg, Long.parseLong(waybillId), !isConsumer);

            throw new BusinessException(messageCode + "", returnMsg);
        }
    }

    /**
     * 回滚订单状态
     *
     * @param lastStatus
     * @param errorMessage
     * @param waybillId
     */
    private void resetOrderStatus(int lastStatus, String errorMessage, Long waybillId, boolean isAppendQueue) throws Exception {
        DWaybill dw = new DWaybill();
        dw.setId(waybillId);
        dw.setUserId(0L);
        dw.setWaybillStatus(DWaybillStatusEnum.SAVE.getValue());
        dWaybillMapper.updateByPrimaryKeySelective(dw);
        LOGGER.info("===dispatchOption===订单回滚操作==");
        // 添加日志
        this.dWaybillStatusHistoryService.add(waybillId, DWaybillStatusTypeEnum.PROCESS.getText(), DWaybillStatusEnum.FAILURE.getText(),
                DWaybillStatusEnum.getByValue(lastStatus).getText(), 0L, errorMessage);
        LOGGER.info("===dispatchOption===添加日志=={}", errorMessage);
        // 加入队列
        if (isAppendQueue) {
            DWaybill dwNew = this.dWaybillMapper.selectByPrimaryKey(waybillId);
            if (null != dwNew) {
                TmsQueueOrderVo tqov = new TmsQueueOrderVo();
                tqov.setFrom(dwNew.getDepartureCity());
                tqov.setTmsSerialNo(dwNew.getOrderLineId().toString());
                tqov.setTo(dwNew.getDestCity());
                tqov.setUrgent(dwNew.getIsUrgent());
                tqov.setWaybillId(waybillId.toString());
                tmsQueueService.appendOrder(tqov);
            }
        }
    }

    // 异步推送派单信息和在途司机实时位置信息
    private int pushMessage(String orderCode, Long orderLineId, SUser user) {
        LOGGER.info("DWaybillServiceImpl.pushMessage params : {}, {}, {}", orderCode, orderLineId, user);

        /**
         * 调用接口返回值
         */
        int returnCode = -1;

        OrderDistributableInfo distributableInfo = new OrderDistributableInfo();

        //  获取d用户
        DUser dUser = dUserService.selectByPhone(user.getPhone());
        if (null == dUser) {
            LOGGER.error("DWaybillServiceImpl.pushMessage dUser must not be null");
            throw new BusinessException(TmsDispatchOptionCodeEnum.DRIVER_INFO_SYSTEM_ERROR.getValue() + "", TmsDispatchOptionCodeEnum.DRIVER_INFO_SYSTEM_ERROR.getText());
        }

        DUserExt dUserExt = dUserExtService.selectByUserId(dUser.getId());
        if (null == dUserExt) {
            LOGGER.error("DWaybillServiceImpl.pushMessage dUserExt must not be null");
            throw new BusinessException(TmsDispatchOptionCodeEnum.DRIVER_INFO_SYSTEM_ERROR.getValue() + "", TmsDispatchOptionCodeEnum.DRIVER_INFO_SYSTEM_ERROR.getText());
        }

        distributableInfo.setVcname(dUserExt.getRealName()); // 司机姓名
        distributableInfo.setVcnative(dUserExt.getBirthplace()); // 籍贯
        distributableInfo.setDtbirthday(dUserExt.getBirthday()); // 出生年月
        distributableInfo.setVccard(dUserExt.getIdNo()); // 身份证号
        distributableInfo.setVchometel(dUserExt.getHomePhone()); // 家庭电话
        distributableInfo.setVchomeaddress(dUserExt.getHomeAddress()); // 住址
        distributableInfo.setVcvouch(dUserExt.getGuarantor()); // 担保人

        /**
         * 获取司机驾照类型
         */
        DUserLicense dUserLicense = dUserLicenseService.selectByUserId(dUser.getId());

        if (null == dUserLicense) {
            LOGGER.error("DWaybillServiceImpl.pushMessage user license must not be null");
            throw new BusinessException(TmsDispatchOptionCodeEnum.DRIVER_HAS_NO_LICENSE.getValue() + "", TmsDispatchOptionCodeEnum.DRIVER_HAS_NO_LICENSE.getText());
        }

        distributableInfo.setDtfirstget(dUserLicense.getReceiveTime()); // 驾照初领时间
        distributableInfo.setVcdept(dUserLicense.getLicenseDept()); // 驾照发证机关
        distributableInfo.setVcdrivestyle(dUserLicense.getLicenseName()); // 驾照类型

        distributableInfo.setVcorderno(orderCode);
        distributableInfo.setOrderilineid(orderLineId);
        distributableInfo.setVcmobile(user.getPhone()); // 手机号
        distributableInfo.setAssigntime(new Date()); // 派单时间

        String tmsDriverNo = dUserExt.getTmsDriverNo();
        tmsDriverNo = StringUtils.isBlank(tmsDriverNo) == true ? ZL_DRIVER_PREFIX + dUserExt.getUserId() : tmsDriverNo;

        distributableInfo.setVcdriverno(tmsDriverNo); // 司机编号
        distributableInfo.setVccommunity(""); // 所属社区
        distributableInfo.setIrateid(1); // 司机等级

        // 中联结果分析处理-----开始----
        String data = this.pushOrderDistributableInfoToTms(distributableInfo);

        // 成功
        if (null != data) {
            JSONObject result = JSONObject.parseObject(data);
            return result.getInteger("messagecode");
        }
        // 中联结果分析处理-----结束----
        return returnCode;
    }

    @Override
    public void updateWaybillStatusAndRecoveryTime(Long waybillId, Integer waybillStatus, Date recoveryTime) {
        LOGGER.info("updateWaybillStatus params : {}, {}, {}", waybillId, waybillStatus, recoveryTime);
        if (null == waybillId) {
            LOGGER.error("updateWaybillStatus param waybillId must not be null");
            throw new IllegalArgumentException("运单主键不能为空");
        }
        /*if (null == waybillStatus) {
            LOGGER.error("updateWaybillStatus param waybillStatus must not be null");
            throw new IllegalArgumentException("运单状态不能为空");
        }*/
        //保存运单状态变更
        //dWaybillStatusHistoryService.add(waybillId, DWaybillStatusTypeEnum.PROCESS.getText(), DWaybillStatusEnum.getByValue(waybillStatus).getText(), DWaybillStatusEnum.getByValue(dWaybillMapper.selectByPrimaryKey(waybillId).getWaybillStatus()).getText(), 0L, "系统回单");
        //如果回单时间不为空，则更新回单时间
        if (null != recoveryTime) {
            DWaybill waybill = new DWaybill();
            waybill.setId(waybillId);
            //waybill.setWaybillStatus(waybillStatus);
            waybill.setRecoveryTime(recoveryTime);
            dWaybillMapper.updateByPrimaryKeySelective(waybill);
        }
    }

    @Override
    public String pushOrderDistributableInfoToTms(OrderDistributableInfo distributableInfo) {
        LOGGER.info("pushOrderDistributableInfoToTms params : {}", distributableInfo);
        final String url = TmsUrlConstant.PUSH_DISTRIBUTABLE_INFO;
        Map<String, Object> paramsMap = new HashMap<>();
        this.bean2Map(paramsMap, distributableInfo);
        return tmsOrderCallHistoryService.urlCall(url, TmsUrlTypeEnum.PUSH_DISTRIBUTABLE_INFO.getValue(), paramsMap, 30000);
    }

    private void bean2Map(Map<String, Object> paramsMap, Object obj) {
        BeanInfo beanInfo = null;
        try {
            beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();

                // 过滤class属性
                if (!key.equals("class")) {
                    // 得到property对应的getter方法
                    Method getter = property.getReadMethod();
                    Object value = getter.invoke(obj);

                    paramsMap.put(key, value);
                }
            }
        } catch (IntrospectionException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    @Override
    public String pushOrderArrivalInfo(OrderArrivalInfo arrivalInfo) {
        LOGGER.info("pushOrderArrivalInfo params : {}", arrivalInfo);
        final String url = TmsUrlConstant.PUSH_ARRIVAL_CONFIRMATION;

        Map<String, Object> paramsMap = new HashMap<>();
        this.bean2Map(paramsMap, arrivalInfo);
        return tmsOrderCallHistoryService.urlCall(url, TmsUrlTypeEnum.PUSH_ARRIVAL_CONFIRMATION.getValue(), paramsMap, 10000);
    }

    @Override
    public String pushOrderDriverLocation(OrderDriverLocationInfo locationInfo) {
        LOGGER.info("pushOrderDriverLocation params : {}", locationInfo);
        final String url = TmsUrlConstant.PUSH_DRIVER_LOCATION;
        Map<String, Object> paramsMap = new HashMap<>();
        this.bean2Map(paramsMap, locationInfo);
        return tmsOrderCallHistoryService.urlCall(url, TmsUrlTypeEnum.PUSH_DRIVER_LOCATION.getValue(), paramsMap, 10000);
    }

    @Override
    public Boolean orderIsDispatched(Long orderLineId) {
        LOGGER.info("dwaybill orderIsDispatched params orderLineId : {}.", orderLineId);
        DWaybillExample example = new DWaybillExample();
        example.createCriteria().andOrderLineIdEqualTo(orderLineId);
        List<DWaybill> dWaybills = dWaybillMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(dWaybills)) {
            throw new BusinessException("运单不存在");
        }
        DWaybill dWaybill = dWaybills.get(0);
        if (null != dWaybill) {
            Long userId = dWaybill.getUserId();
            Integer waybillStatus = dWaybill.getWaybillStatus();

            if (null != userId && 0 != userId && waybillStatus > 0) {
                return false;
            }
        }
        return true;
    }

    @Override
    public DWaybill getByPrimaryId(Long waybillId) {
        LOGGER.info("getByPrimaryId param : {}", waybillId);
        if (null == waybillId) {
            LOGGER.error("getByPrimaryId param must not be null");
            throw new IllegalArgumentException("运单主键不能为空");
        }
        return dWaybillMapper.selectByPrimaryKey(waybillId);
    }

    @Override
    public DWaybill getByTmsOrderCode(String orderCode) {
        LOGGER.info("getByTmsOrderCode param : {}", orderCode);
        if (StringUtils.isBlank(orderCode)) {
            LOGGER.error("getByTmsOrderCode orderCode must not be null");
            throw new IllegalArgumentException("订单编号不能为空");
        }

        DWaybillExample example = new DWaybillExample();
        example.createCriteria().andOrderCodeEqualTo(orderCode);

        List<DWaybill> list = dWaybillMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(list)) {
            LOGGER.error("getByTmsOrderCode list is empty");
            return null;
        }

        return list.get(0);
    }

    @Override
    public void updateSelective(DWaybill waybill) {
        LOGGER.info("updateSelective params : {}", waybill);
        dWaybillMapper.updateByPrimaryKeySelective(waybill);
    }

    @Override
    public Result<Map<String, Object>> list(PageVo pageVo, DWaybill dWaybill) throws Exception {
        LOGGER.info("list params pageVo: {}, Dwaybill: {}", pageVo, dWaybill);
        Result<Map<String, Object>> result = new Result<>(true, null, "数据加载成功");
        Map<String, Object> map = new HashMap<>();
        DWaybillExample example = new DWaybillExample();
        DWaybillExample.Criteria criteria = example.createCriteria();
        criteria.andIsDamageEqualTo(WaybillIsDamageEnum.T.getValue());
        if (StringUtils.isNotBlank(dWaybill.getOrderCode())) {
            criteria.andOrderCodeEqualTo(dWaybill.getOrderCode());
        }
        int count = dWaybillMapper.countByExample(example);
        LOGGER.info("totalRecord : {}", count);
        pageVo.setTotalRecord(count);
        example.setLimitStart(pageVo.getStartIndex());
        example.setLimitEnd(pageVo.getPageSize());
        List<DWaybill> lists = dWaybillMapper.selectByExample(example);
        LOGGER.info("lists.size : {}", lists.size());
        map.put("waybillList", lists);
        map.put("page", pageVo);
        result.setData(map);
        return result;
    }

    @Override
    public Result<Map<String, Object>> tmsList(PageVo pageVo, DWaybill dWaybill) throws Exception {
        LOGGER.info("list params pageVo: {}, Dwaybill: {}", pageVo, dWaybill);
        Result<Map<String, Object>> result = new Result<>(true, null, "数据加载成功");
        Map<String, Object> map = new HashMap<>();
        DWaybillExample example = new DWaybillExample();
        DWaybillExample.Criteria criteria = example.createCriteria();
        criteria.andWaybillStatusEqualTo(DWaybillStatusEnum.INTRANSIT.getValue());
        if (StringUtils.isNotBlank(dWaybill.getOrderCode())) {
            criteria.andOrderCodeEqualTo(dWaybill.getOrderCode());
        }
        int count = dWaybillMapper.countByExample(example);
        LOGGER.info("totalRecord : {}", count);
        pageVo.setTotalRecord(count);
        example.setLimitStart(pageVo.getStartIndex());
        example.setLimitEnd(pageVo.getPageSize());
        List<DWaybill> lists = dWaybillMapper.selectByExample(example);
        LOGGER.info("lists.size : {}", lists.size());
        map.put("waybillList", lists);
        map.put("page", pageVo);
        result.setData(map);
        return result;
    }

    @Override
    public Result<String> cancelDWaybillWithUser(Long waybillId) throws Exception {
        LOGGER.info("cancelDWaybillWithUser params waybillId: {}", waybillId);
        if (waybillId == null) {
            LOGGER.error("cancelDWaybillWithUser param waybillId must not be null");
            throw new IllegalArgumentException("运单ID不能为空！");
        }
        Result<String> result = new Result<>(true, "退单成功！");
        try {
            DWaybill waybill = dWaybillMapper.selectByPrimaryKey(waybillId);
            Long userId = waybill.getUserId();
            waybill.setUserId(0L);
            waybill.setWaybillStatus(DWaybillStatusEnum.CANCEL.getValue());
            waybill.setOperationStatus(TmsOrderOperationStatusEnum.CANCEL.getValue());
            // 解绑用户与运单关联
            dWaybillMapper.updateByPrimaryKeySelective(waybill);
            // 添加日志
            this.dWaybillStatusHistoryService.add(waybill.getId(), DWaybillStatusTypeEnum.OPERATION.getText(), TmsOrderOperationStatusEnum.CANCEL.getText(),
                    DWaybillStatusEnum.getByValue(waybill.getWaybillStatus()).getText(), 0L, "中联取消");
            // 用户下线
            SUser user = userService.selectByPrimaryKey(userId);
            if (user == null) {
                LOGGER.info("user is not find");
                throw new BusinessException("用户不存在");
            }
            user.setUserStatus(UserStatusEnum.F.getValue());
            userService.updateByRecord(user);
        } catch (Exception e) {
            LOGGER.error("cancelDWaybillWithUser error : {}", e);
            throw new BusinessException("退单失败！");
        }
        return result;
    }

    @Override
    public Result<Object> damageAudit(Long waybillId, int status) throws Exception {
        LOGGER.info("damageAudit params waybillId: {}, status: {}", waybillId, status);
        Result<Object> result = new Result<>(true, null, "审核成功");
        if (waybillId == null || waybillId == 0) {
            LOGGER.info("waybillId is not null");
            throw new BusinessException("运单ID不能为空");
        }
        int num = DWaybillDamageAuditEnum.getByValue(status).getValue();
        if ("".equals(num)) {
            LOGGER.info("status is not null");
            throw new BusinessException("审核状态不能为空");
        }
        DWaybill dWaybill = new DWaybill();
        dWaybill.setId(waybillId);
        dWaybill.setDamageAudit(num);
        result.setData(dWaybillMapper.updateByPrimaryKeySelective(dWaybill));
        return result;
    }

    @Override
    public Result<Map<String, Object>> currentWaybill() throws Exception {
        UserShowVo vo = userService.getCurrentUser();
        Result<Map<String, Object>> result = new Result<>(true, null, "数据加载成功");
        Map<String, Object> map = new HashMap<>();
        if (null == vo) {
            LOGGER.info("current user is null");
            throw new BusinessException("当前用户不存在");
        }
        DWaybillExample example = new DWaybillExample();
        example.createCriteria().andUserIdEqualTo(vo.getId()).andWaybillStatusEqualTo(DWaybillStatusEnum.INTRANSIT.getValue());
        List<DWaybill> lists = dWaybillMapper.selectByExample(example);
        if (CollectionUtils.isNotEmpty(lists)) {
            DWaybill dWaybill = lists.get(0);
            DAccidentExample dAccidentExample = new DAccidentExample();
            dAccidentExample.createCriteria().andWaybillIdEqualTo(dWaybill.getId());
            List<DAccident> dAccidents = dAccidentMapper.selectByExample(dAccidentExample);
            map.put("id", dWaybill.getId());
            map.put("orderCode", dWaybill.getOrderCode());
            if (CollectionUtils.isNotEmpty(dAccidents)) {
                map.putIfAbsent("auditStatus", dAccidents.get(0).getStatus());
            }
            map.putIfAbsent("auditStatus", 0);
            result.setData(map);
            return result;
        }
        return result;
    }

    @Override
    public List<SupplierCWListVo> selectByDepaAndDest(String depaName, String destName, Integer num) {
        LOGGER.info("selectByDest params : {}, {}, {}", depaName, destName, num);
        if (StringUtils.isBlank(depaName)) {
            LOGGER.error("selectByDest param depaName must not be null");
            throw new IllegalArgumentException("起始地名车不能为空");
        }
        if (StringUtils.isBlank(destName)) {
            LOGGER.error("selectByDest param destName must not be null");
            throw new IllegalArgumentException("目的地名车不能为空");
        }

        Map<String, Object> paramsMap = new HashMap<>();
        paramsMap.put("status", Arrays.asList(DWaybillStatusEnum.SAVE.getValue()));
        paramsMap.put("depaName", depaName);
        paramsMap.put("destName", destName);
        if (null != num) {
            paramsMap.put("limitStart", 0);
            paramsMap.put("limitEnd", num);
        }

        List<SupplierCWListVo> dWaybillList = dWaybillViewMapper.getListByCondationsForSupplier(paramsMap);
        if (CollectionUtils.isNotEmpty(dWaybillList)) {
            return dWaybillList;
        }

        return null;
    }

    @Override
    public Map<String, Object> getListByPageAndConditions(PageVo page, List<Integer> waybillStatus, Map<String, Object> paramsMap) {
        Map<String, Object> resultMap = new HashMap<>();

        //运单状态
        if (CollectionUtils.isNotEmpty(waybillStatus)) {
            paramsMap.put("status", waybillStatus);
        }

        //分页参数
        if (null != page) {
            String orderByClause = StringUtils.isNotBlank(page.getOrder()) == true ? page.getOrder()
                    : " dw.create_time DESC ";
            paramsMap.put("limitStart", page.getStartIndex());
            paramsMap.put("limitEnd", page.getPageSize());
            paramsMap.put("orderByClause", orderByClause);

            page.setTotalRecord(dWaybillViewMapper.countByCondationsForSupplier(paramsMap));
        }

        if (null != page) {
            resultMap.put("page", page);
        }

        List<SupplierCWListVo> list = dWaybillViewMapper.getListByCondationsForSupplier(paramsMap);
        resultMap.put("list", list);

        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(vo -> vo.setStatusTest(DWaybillStatusEnum.getByValue(vo.getStatus()).getText()));
        }

        return resultMap;
    }

    @Override
    public DWaybill selectByPrimaryKeyAndUserIdAndWaybillStatus(Long wid, Long userId, Integer waybillStatus) {
        LOGGER.info("selectByPrimaryKeyAndUserIdAndWaybillStatus params : {}, {}, {}", wid, userId, waybillStatus);
        if (null == wid) {
            LOGGER.error("selectByPrimaryKeyAndUserIdAndWaybillStatus param wid must not be null");
            throw new IllegalArgumentException("运单主键不能为空");
        }

        DWaybillExample example = new DWaybillExample();
        DWaybillExample.Criteria criteria = example.createCriteria().andIdEqualTo(wid);
        if (null != userId) {
            criteria.andUserIdEqualTo(userId);
        }
        if (null != waybillStatus) {
            criteria.andWaybillStatusEqualTo(waybillStatus);
        }

        List<DWaybill> list = dWaybillMapper.selectByExample(example);
        if (CollectionUtils.isNotEmpty(list)) {
            return list.get(0);
        }

        return null;
    }

    @Override
    public Long add(DWaybill waybill) {
        LOGGER.info("add params : {}", waybill);
        if (null == waybill) {
            LOGGER.error("add params waybill must not be null");
            throw new IllegalArgumentException("运单信息不能为空");
        }

        dWaybillMapper.insertSelective(waybill);

        return waybill.getId();
    }

    @Override
    public BigDecimal calcDWaybillCost(Long waybillId, OrderCostTo orderCostTo, boolean isUpdate) throws Exception {
        LOGGER.info("calcDWaybillCost params : {}, {}, {}", waybillId, orderCostTo, isUpdate);
        if (null == waybillId) {
            LOGGER.error("calcDWaybillCost param waybillId must not be null");
            throw new IllegalArgumentException("运单主键不能为空");
        }

        if (null == orderCostTo) {
            LOGGER.error("calcDWaybillCost param orderCostTo must not be null");
            throw new IllegalArgumentException("费用信息不能为空");
        }

        Map<String, BigDecimal> fees = new HashMap<>();

        //总费用 = km * price --> 总公里*每公里单价
        BigDecimal originalTotalCost = BigDecimal.ZERO.setScale(2);
        BigDecimal confirmTotalCost = BigDecimal.ZERO.setScale(2);

        //总油量(L) = kilometer * fuelstandard / 100 --> 行驶里程（加油计算里程）* 百公里油耗/100
        BigDecimal totalFuelConsumption = BigDecimal.ZERO.setScale(2);

        //总油费(元) = 总油量 * marketprice --> 总油量 * 市场挂牌油价
        BigDecimal totalFuelCost = BigDecimal.ZERO.setScale(2);

        //运费(元)：总费用 -  总油费
        BigDecimal totalShippingCost = BigDecimal.ZERO.setScale(2);

        if (null != orderCostTo) {
            if (orderCostTo.getKm().compareTo(BigDecimal.ZERO) == 1 &&
                    orderCostTo.getPrice().compareTo(BigDecimal.ZERO) == 1) {
                if (!isUpdate) {
                    originalTotalCost = confirmTotalCost = orderCostTo.getKm().multiply(orderCostTo.getPrice()).setScale(2, RoundingMode.UP);
                } else {
                    confirmTotalCost = orderCostTo.getKm().multiply(orderCostTo.getPrice()).setScale(2, RoundingMode.UP);
                }
            }

            if (orderCostTo.getKilometer().compareTo(BigDecimal.ZERO) == 1 &&
                    orderCostTo.getFuelstandard().compareTo(BigDecimal.ZERO) == 1) {
                totalFuelConsumption = orderCostTo.getKilometer().multiply(orderCostTo.getFuelstandard())
                        .divide(BigDecimal.valueOf(100), 2, RoundingMode.UP).setScale(0, RoundingMode.UP).setScale(2);
            }

            if (totalFuelConsumption.compareTo(BigDecimal.ZERO) == 1 &&
                    orderCostTo.getMarketprice().compareTo(BigDecimal.ZERO) == 1) {
                totalFuelCost = totalFuelConsumption.multiply(orderCostTo.getMarketprice()).setScale(2, RoundingMode.UP);
            }

            if (confirmTotalCost.compareTo(BigDecimal.ZERO) == 1) {
                totalShippingCost = confirmTotalCost.subtract(totalFuelCost).setScale(2, RoundingMode.UP);
            }
        }

        fees.put(TOTAL_SHIPPING_FEE_NAME, confirmTotalCost);
        fees.put(OIL_SUBSIDY_FEE_NAME, totalFuelCost);
        fees.put(SHIPPING_FEE_NAME, totalShippingCost);

        //更新运单信息
        DWaybill waybill = new DWaybill();
        waybill.setId(waybillId);

        if (null != orderCostTo) {
            waybill.setDistance(orderCostTo.getKm());//总公里数
            waybill.setPricePerKm(orderCostTo.getPrice());//price
            waybill.setDrivenKilometer(orderCostTo.getKilometer());//行驶里程（加油计算里程）
            waybill.setFirstFuelTotal(orderCostTo.getFirstfueltotal());//第一箱油加油升数
            waybill.setOilPercent(orderCostTo.getOilpercent());//折扣系数

            if (isUpdate) {

                //更新油价信息
                dWaybillOilPriceService.updateByDWaybillId(waybillId, orderCostTo);

                //更新车型油耗和容量
                dWaybillVehicleService.updateByDWaybillId(waybillId, orderCostTo);
            }
        }

        waybill.setTotalFuelConsumption(totalFuelConsumption);//总油耗
        waybill.setTotalFuelCost(totalFuelCost);//总油费
        waybill.setTotalShippingCost(totalShippingCost);//运费
        if (!isUpdate) {
            waybill.setOriginalTotalCost(originalTotalCost);//总费用
        }
        waybill.setConfirmTotalCost(confirmTotalCost);//总费用

        //更新时运费和总费用不能为空，为空则不更新
//		if(isUpdate){
//			if(confirmTotalCost.compareTo(BigDecimal.ZERO) ==1 ){
////				waybill.setOriginalTotalCost(originalTotalCost);
//				waybill.setConfirmTotalCost(confirmTotalCost);
//			}
//			if(totalShippingCost.compareTo(BigDecimal.ZERO) ==1 ){
//				waybill.setTotalShippingCost(totalShippingCost);
//			}
//		}else {
//			waybill.setTotalShippingCost(totalShippingCost);
//			waybill.setOriginalTotalCost(originalTotalCost);
//			waybill.setConfirmTotalCost(confirmTotalCost);
//		}

        this.updateSelective(waybill);

        if (!fees.isEmpty()) {
            Set<String> set = fees.keySet();
            set.forEach(fee -> {
                String key = fee;
                BigDecimal value = fees.get(fee);

                DWaybillFeeDetail feeDetail = new DWaybillFeeDetail();
                if (!isUpdate) {
                    feeDetail.setCostType(DWaybillFeeDetailCostTypeEnum.CREATE_COST.getText());
                } else {
                    feeDetail.setCostType(DWaybillFeeDetailCostTypeEnum.RETURN_COST.getText());
                }
                feeDetail.setWaybillId(waybillId);
                feeDetail.setFeeId(dWaybillFeeTypeService.getIdByConditions(key));
                feeDetail.setFeeName(key);
                feeDetail.setCost(value);
                dWaybillFeeDetailService.add(feeDetail);
            });

        }

        return originalTotalCost;
    }

    public Map<String, Object> selectDriver3rdDone(PageVo page, Map<String, Object> paramsMap) {
        LOGGER.info("select driver 3rd done list paramsMap : {}.", paramsMap);
        try {
            page.setTotalRecord(dWaybillViewMapper.countDoneList(paramsMap));
            List<DWaybillDoneVo> list = dWaybillViewMapper.getDoneList(paramsMap);

            Map<String, Object> map = new HashMap<>();
            map.put("page", page);
            map.put("list", list);
            return map;
        } catch (Exception e) {
            LOGGER.error("select driver 3rd done list paramsMap : {}, error : {}.", paramsMap, e);
            throw new BusinessException("查询分供方出车记录异常");
        }
    }

    @Override
    public List<DWaybillPriceDetailVo> selectPriceById(Long waybillId) {
        try {
            LOGGER.info("select dwaybill fee detail params waybillId : {}.", waybillId);
            List<DWaybillPriceDetailVo> detailVo = new ArrayList<>();
            DWaybillPriceVo priceDetailVos = dWaybillViewMapper.getPriceById(waybillId);
            BigDecimal marketOilPrice = priceDetailVos == null ? BigDecimal.ZERO.setScale(2, BigDecimal.ROUND_UP) : priceDetailVos.getMarketOilPrice();
            BigDecimal totalFuelConsumption = priceDetailVos == null ? BigDecimal.ZERO.setScale(2, BigDecimal.ROUND_UP) : priceDetailVos.getTotalFuelConsumption();
            BigDecimal totalFuelCost = priceDetailVos == null ? BigDecimal.ZERO.setScale(2, BigDecimal.ROUND_UP) : priceDetailVos.getTotalFuelCost();
            BigDecimal totalShippingCost = priceDetailVos == null ? BigDecimal.ZERO.setScale(2, BigDecimal.ROUND_UP) : priceDetailVos.getTotalShippingCost();
            LOGGER.info("select dwaybill fee detail params waybillId : {}, priceDetailVos : {}.", waybillId, priceDetailVos);

            DWaybillPriceDetailVo detailVonew = new DWaybillPriceDetailVo();
            detailVonew.setPrice(totalShippingCost);
            detailVonew.setPriceText("¥" + totalShippingCost);
            detailVonew.setText("运费");
            detailVo.add(detailVonew);
            LOGGER.info("select dwaybill fee detail params waybillId : {}, detailVonew : {}.", waybillId, detailVonew);

            DWaybillPriceDetailVo detailVonew2 = new DWaybillPriceDetailVo();
            detailVonew2.setPrice(totalFuelCost);
            detailVonew2.setPriceText("¥" + totalFuelCost);
            detailVonew2.setText("油费");
            detailVo.add(detailVonew2);
            LOGGER.info("select dwaybill fee detail params waybillId : {}, detailVonew2 : {}.", waybillId, detailVonew2);

            DWaybillPriceDetailVo detailVonew3 = new DWaybillPriceDetailVo();
            detailVonew3.setPrice(totalFuelConsumption);
            detailVonew3.setPriceText(totalFuelConsumption + "L");
            detailVonew3.setText("油量");
            detailVo.add(detailVonew3);
            LOGGER.info("select dwaybill fee detail params waybillId : {}, detailVonew3 : {}.", waybillId, detailVonew3);

            DWaybillPriceDetailVo detailVonew4 = new DWaybillPriceDetailVo();
            detailVonew4.setPrice(marketOilPrice);
            detailVonew4.setPriceText(marketOilPrice + "¥/L");
            detailVonew4.setText("油价");
            detailVo.add(detailVonew4);
            LOGGER.info("select dwaybill fee detail params waybillId : {}, detailVonew4 : {}.", waybillId, detailVonew4);
            return detailVo;
        } catch (Exception e) {
            LOGGER.error("select dwaybill fee detail params waybillId : {}, error : {}.", waybillId, e);
            throw new BusinessException("查询运单价格明细异常");
        }
    }

    @Override
    public List<DWaybill> getListByUsersId(List<Long> userIds) {
        LOGGER.info("getListByUsersId params : {}", userIds);

        DWaybillExample example = new DWaybillExample();
        example.createCriteria().andUserIdIn(userIds);

        List<DWaybill> dWaybills = dWaybillMapper.selectByExample(example);
        if (CollectionUtils.isNotEmpty(dWaybills)) {
            return dWaybills;
        }

        return null;
    }

    @Override
    public boolean hasIntransitDWaybillForUser(Long userId) throws Exception {
        LOGGER.info("hasIntransitDWaybillForUser param : {}", userId);

        List<Integer> status = Arrays.asList(DWaybillStatusEnum.DEPARTURE.getValue(),
                DWaybillStatusEnum.INTRANSIT.getValue(),
                DWaybillStatusEnum.DEAL_CAR.getValue());
        List<Integer> types = Arrays.asList(DWaybillTypeEnum.NORMAL.getValue(),
                DWaybillTypeEnum.QUICK.getValue());

        List<DWaybill> waybills = this.selectDwaybillByUserId(userId, status,types);

        return CollectionUtils.isNotEmpty(waybills) == true ? true : false;
    }

    @Override
    public List<DWaybill> selectListByIds(List<Long> ids) {
        LOGGER.info("DWaybillServiceImpl.selectListByIds param : {}", ids.size());
        if (CollectionUtils.isEmpty(ids)) {
            LOGGER.error("DWaybillServiceImpl.selectListByIds param ids must not be null");
            throw new IllegalArgumentException("运单主键不能为空");
        }

        DWaybillExample example = new DWaybillExample();
        example.createCriteria().andIdIn(ids);

        return dWaybillMapper.selectByExample(example);
    }

    @Override
    public DWaybill selectByOrderLineId(Long orderLineId) {
        LOGGER.info("selectByOrderLineId param : {}", orderLineId);
        if (null == orderLineId) {
            LOGGER.error("selectByOrderLineId param orderLineId must not be null");
            throw new IllegalArgumentException("TMS订单主键不能为空");
        }

        DWaybillExample example = new DWaybillExample();
        example.createCriteria().andOrderLineIdEqualTo(orderLineId);

        List<DWaybill> dWaybills = dWaybillMapper.selectByExample(example);
        if (CollectionUtils.isNotEmpty(dWaybills)) {
            return dWaybills.get(0);
        }

        return null;
    }

    @Override
    public List<DWaybill> selectListByStatus(List<Integer> status) {
        LOGGER.info("DWaybillServiceImpl.selectListByStatus");
        if (CollectionUtils.isEmpty(status)) {
            LOGGER.error("DWaybillServiceImpl.selectListByStatus param status must not be empty");
            throw new IllegalArgumentException("状态不能为空");
        }

        DWaybillExample example = new DWaybillExample();
        example.createCriteria().andWaybillStatusIn(status);

        return dWaybillMapper.selectByExample(example);
    }

    @Override
    public void updateIsError(Long id) {
        LOGGER.info("DWaybillServiceImpl.updateIsError param : {}", id);

        if (null == id) {
            LOGGER.error("DWaybillServiceImpl.updateIsError param id must not be null");
            throw new IllegalArgumentException("主键不能为空");
        }

        DWaybill waybill = new DWaybill();
        waybill.setId(id);
        waybill.setIsError(true);
        this.updateSelective(waybill);

    }

    @Override
    public List<DWaybill> selectByExample(DWaybillExample example) {
        LOGGER.info("DWaybillServiceImpl.selectByExample param : {}", example);

        return dWaybillMapper.selectByExample(example);
    }

    @Override
    public void updateIsDispatch(Long userId, Long waybillId, Date dispatchDate, Integer waybillStatus) {
        LOGGER.info("DWaybillServiceImpl.updateIsDispatch params : {}, {}, {}, {}", userId, waybillId, dispatchDate, waybillStatus);

        if (null == userId || 0 == userId.longValue()) {
            LOGGER.info("DWaybillServiceImpl.updateIsDispatch param userId must not be null");
            throw new IllegalArgumentException("用户主键不能为空");
        }
        if (null == waybillId || 0 == waybillId.longValue()) {
            LOGGER.info("DWaybillServiceImpl.updateIsDispatch param waybillId must not be null");
            throw new IllegalArgumentException("运单主键不能为空");
        }
        if (null == dispatchDate) {
            LOGGER.info("DWaybillServiceImpl.updateIsDispatch param dispatchDate must not be null");
            throw new IllegalArgumentException("派单时间不能为空");
        }
        if (null == waybillStatus) {
            LOGGER.info("DWaybillServiceImpl.updateIsDispatch param waybillStatus must not be null");
            throw new IllegalArgumentException("运单状态不能为空");
        }

        DWaybill waybill = new DWaybill();
        waybill.setId(waybillId);
        waybill.setUserId(userId);
        waybill.setDispatchTime(dispatchDate);
        waybill.setWaybillStatus(waybillStatus); // 待发运
        dWaybillMapper.updateByPrimaryKeySelective(waybill);
    }

    @Override
    public Map<String, Object> getDeliveryListByPage(PageVo page, String orderCode,String waybillstatus, String beginDate, String endDate) {
        // 查询运单信息
        List<Integer> statusList = new ArrayList<>();
        statusList.add(Integer.valueOf(waybillstatus));
        Map<String, Object> map = new HashMap<>();

        try {
            Map<String, Object> paramsMap = new HashMap<>();
            String orderByClause = StringUtils.isNotBlank(page.getOrder()) == true ? page.getOrder()
                    : " tdv.gmt_create asc";
            paramsMap.put("status", statusList);
            if (!Strings.isNullOrEmpty(orderCode)) {
                paramsMap.put("orderCode", orderCode);
            }
            if (!Strings.isNullOrEmpty(beginDate)) {
                paramsMap.put("beginDate", beginDate);
            }
            if (!Strings.isNullOrEmpty(endDate)) {
                paramsMap.put("endDate", endDate);
            }
            //默认查询第一次上传的结果
            paramsMap.put("isFirstUpload", true);
            page.setTotalRecord(this.dWaybillViewMapper.countByWayStatus(paramsMap));
            paramsMap.put("limitStart", page.getStartIndex());
            paramsMap.put("limitEnd", page.getPageSize());
            paramsMap.put("orderByClause", orderByClause);
            List<DWaybillDetailVo> dWaybillList = this.dWaybillViewMapper.getDWaybillListByCondition(paramsMap);
            map.put("page", page);
            map.put("dWaybillList", dWaybillList);
            return map;
        } catch (Exception e) {
            LOGGER.error("select current user dwaybill list error : {}.", e);
            throw new BusinessException("查询当前用户运单列表异常");
        }
    }

    @Override
    public Map<String, Object> getListByCodePage(PageVo page, String orderCode) {

        // 查询运单信息
        List<Integer> statusList = new ArrayList<>();
        statusList.add(DWaybillStatusEnum.DEPARTURE.getValue());
        statusList.add(DWaybillStatusEnum.INTRANSIT.getValue());

        Map<String, Object> map = new HashMap<>();

        try {
            Map<String, Object> paramsMap = new HashMap<>();
            String orderByClause = StringUtils.isNotBlank(page.getOrder()) == true ? page.getOrder()
                    : " dw.id DESC";
            paramsMap.put("status", statusList);
            if (!Strings.isNullOrEmpty(orderCode)) {
                paramsMap.put("orderCode", orderCode);
            }
            page.setTotalRecord(this.dWaybillViewMapper.countByWayStatus4Lock(paramsMap));
            paramsMap.put("limitStart", page.getStartIndex());
            paramsMap.put("limitEnd", page.getPageSize());
            paramsMap.put("orderByClause", orderByClause);
            List<DWaybillDetailVo> dWaybillList = this.dWaybillViewMapper.getDWaybillListByCondition4Lock(paramsMap);
            map.put("page", page);
            map.put("dWaybillList", dWaybillList);
            return map;
        } catch (Exception e) {
            LOGGER.error("select current user dwaybill list error : {}.", e);
            throw new BusinessException("查询当前用户运单列表异常");
        }

    }


    @Override
    public Boolean updateWaybillDeliveryStatus(Long waybillId, int checkstatus, String checkMark, String attachs)
            throws BusinessException {
        Boolean blnRtn = false;
        LOGGER.info("updateWaybillDeliveryStatus params waybillId: {}", waybillId);
        if (waybillId == null) {
            LOGGER.error("updateWaybillDeliveryStatus param waybillId must not be null");
            throw new IllegalArgumentException("运单ID不能为空！");
        }
        try {
            int count = 0;
            DWaybill waybill = dWaybillMapper.selectByPrimaryKey(waybillId);
            waybill.setDeliveryCheckStatus(checkstatus);
            waybill.setCheckDeliveryRemark(checkMark);
            //更新审核信息
            dWaybillMapper.updateByPrimaryKeySelective(waybill);
            //保存图片
            Long user_id = waybill.getUserId();
            SUser user = sUserMapper.selectByPrimaryKey(user_id);
            UserShowVo userShowVo = new UserShowVo();
            this.userService.buildUserShowVo(user, userShowVo);
            List<AttachForm> objs = JSONArray.parseArray(attachs, AttachForm.class);
            if (CollectionUtils.isNotEmpty(objs)) {
                AttachForm af;
                DWaybillAttach attach = new DWaybillAttach();
                attach.setWaybillId(waybill.getId());
                attach.setUserId(waybill.getUserId());
                attach.setUserName(user.getRealName());
                attach.setCategory(AttachCategoryEnumWaybill.DELIVER.getValue());// 交车照片

                String urls = "";
                for (int i = 0; i < objs.size(); i++) {
                    af = objs.get(i);
                    attach.setPicKey(af.getImage());
                    if (StringUtils.isEmpty(urls)) {
                        urls = urls.concat(QiniuUtils.generateDownloadTicket(attach.getPicKey(), ""));
                    } else {
                        urls = urls.concat(",").concat(QiniuUtils.generateDownloadTicket(attach.getPicKey(), ""));
                    }
                    AttachTypeEnum typeEnum = AttachTypeEnum.getByValue(af.getType());
                    if (typeEnum == null) {
                        LOGGER.error("typeEnum is null");
                        throw new BusinessException("图片类型错误!");
                    }
                    attach.setType(typeEnum.getValue());
                    // 照片去重
                    DWaybillAttachExample attachExample = new DWaybillAttachExample();
                    attachExample.createCriteria().andWaybillIdEqualTo(waybill.getId()).andCategoryEqualTo(AttachCategoryEnumWaybill.DELIVER.getValue()).andTypeEqualTo(typeEnum.getValue());
                    List<DWaybillAttach> attachlist = this.dWaybillAttachMapper.selectByExample(attachExample);
                    if (CollectionUtils.isEmpty(attachlist)) {
                        count += this.dWaybillAttachMapper.insertSelective(attach);
                    } else {
                        Long oldId = attachlist.get(0).getId();
                        attach.setId(oldId);
                        count += this.dWaybillAttachMapper.updateByPrimaryKeySelective(attach);
                    }
                }

                if (count > 0) {
                    // 运单到达了要调用这个接口 推送订单到达信息到TMS系统中
                    boolean pushMessageFlag = this.pushMessage(null, userShowVo, waybill.getOrderCode(), waybill.getOrderLineId(), urls);
                    LOGGER.info("upload confirmDliver picture zl interface error waybillid : {}, params upv:{}, user:{}, waybillCode:{}, orderLindId:{}, urls:{}.", waybillId, null, user, waybill.getOrderCode(), waybill.getOrderLineId(), urls);
                    if (!pushMessageFlag) {
                        LOGGER.info("upload confirmDliver picture zl interface error waybillid : {}, result : {}.", waybillId, pushMessageFlag);
                        // throw new BusinessException("确认交车,中联接口调用失败");
                    }
                }

            }

            //审核不通过 发送推送消息
            if (checkstatus == 1) {
                SUserDevicesExample example = new SUserDevicesExample();
                example.setOrderByClause("id desc");
                example.createCriteria().andUserIdEqualTo(waybill.getUserId());
                LOGGER.info("waybill.getUserId(): {}", waybill.getUserId());
                List<SUserDevices> sUserDevices = sUserDevicesMapper.selectByExample(example);
                LOGGER.info("sUserDevices size: {}", sUserDevices.size());
                if (CollectionUtils.isNotEmpty(sUserDevices)) {
                    SUserDevices devices = sUserDevices.get(0);
                    LOGGER.info("SUserDevices: {}", devices);
                    List<String> aliases = new ArrayList<String>();
                    aliases.add(devices.getUuid().replaceAll("-", "").replaceAll("_", ""));
                    LOGGER.info("aliases: {}", devices.getUuid().replaceAll("-", "").replaceAll("_", ""));
                    // 推送消息
                    String msg = "尊敬的司机，您的" + "从" + waybill.getDepartureCity() + "至" + waybill.getDestCity() + "的运单审核未通过，未通过的原因："
                            + checkMark;
                    LOGGER.info("msg: {}, devices: {}", msg, devices.getUuid());
                    jPushService.sendMsgDriverByAliases(aliases, msg, "0");
                }
            }

            blnRtn = true;
        } catch (Exception e) {
            LOGGER.error("updateWaybillDeliveryStatus error : {}", e);
            throw new BusinessException("审核操作失败！");
        }
        return blnRtn;
    }

    @Override
    public String getDeliveryPhotoAddress(Long id) {
        DWaybill dwaybill = dWaybillMapper.selectByPrimaryKey(id);
        String strPhotoAddress = "";

        if (dwaybill != null) {
            Long userId = dwaybill.getUserId();

            String statusType = DWaybillStatusTypeEnum.PROCESS.getText();
            String currentStatus = DWaybillStatusEnum.getByValue(DWaybillStatusEnum.DEAL_CAR.getValue()).getText();
            DWaybillStatusHistory dWaybillStatusHistory = this.dWaybillStatusHistoryService.getWaybillStatusHistoryById(id, statusType, currentStatus);
            if (dWaybillStatusHistory != null) {
                DateTime dt = new DateTime(dWaybillStatusHistory.getCreateTime());

                DUserPositionExample example = new DUserPositionExample();
                example.setOrderByClause(" create_time asc ");
                example.createCriteria().andUserIdEqualTo(userId)
                        .andCreateTimeGreaterThanOrEqualTo(dt.withMillisOfDay(0).toDate())
                        .andCreateTimeLessThan(dt.withMillisOfDay(0).plusDays(1).toDate());
                List<DUserPosition> dups = dUserPositionMapper.selectByExample(example);
                if (CollectionUtils.isNotEmpty(dups)) {
                    strPhotoAddress = dups.get(0).getAddress();
                }
            }

        }

        return strPhotoAddress;
    }

    @Override
    public Boolean updateWaybillCheckLocalPIC(Long waybillId, Boolean isCheck) {
        Boolean blnRtn = false;
        LOGGER.info("updateWaybillCheckLocalPIC params waybillId: {}", waybillId);
        if (waybillId == null) {
            LOGGER.error("updateWaybillCheckLocalPIC param waybillId must not be null");
            throw new IllegalArgumentException("运单ID不能为空！");
        }

        try {
            DWaybill waybill = dWaybillMapper.selectByPrimaryKey(waybillId);
            waybill.setIsCheckLocalPic(isCheck);
            //更新照片锁定信息
            dWaybillMapper.updateByPrimaryKeySelective(waybill);
            blnRtn = true;
        } catch (Exception e) {
            LOGGER.error("updateWaybillDeliveryStatus error : {}", e);
            throw new BusinessException("操作失败！");
        }

        return blnRtn;
    }

    @Override
    public Map<String, Object> getWaybillListByOrderCodeAndPhone(PageVo page, String orderCode, String phone) {
        LOGGER.info("DWaybillServiceImpl.getWaybillListByOrderCodeAndPhone params: orderCode: {}, phone: {}", orderCode, phone);
        Map<String, Object> map = new HashMap<>();

        try {
            Map<String, Object> paramsMap = new HashMap<>();
            paramsMap.put("limitStart", page.getStartIndex());
            paramsMap.put("limitEnd", page.getPageSize());

            if (StringUtils.isNotBlank(orderCode)) {
                paramsMap.put("orderCode", orderCode);
            }
            if (StringUtils.isNotBlank(phone)) {
                paramsMap.put("phone", phone);
            }

            page.setTotalRecord(this.dWaybillViewMapper.countDWaybillListByOrderCodeAndPhone(paramsMap));
            List<DWaybillVo> dWaybillList = this.dWaybillViewMapper.getDWaybillListByOrderCodeAndPhone(paramsMap);

            map.put("page", page);
            map.put("dWaybillList", dWaybillList);
            return map;
        } catch (Exception e) {
            LOGGER.error("select current user dwaybill list error : {}.", e);
            throw new BusinessException("查询当前用户运单列表异常");
        }
    }

    @Override
    public Map<Integer, Object> addDWaybillCost(final DWaybillFeeDetailCostTypeEnum typeEnum, DWaybill waybill) throws Exception {
        LOGGER.info("DWaybillServiceImpl.buildDWaybillCost params : {}", typeEnum, waybill);

        if (null == waybill) {
            LOGGER.error("DWaybillServiceImpl.buildDWaybill param waybill must not be null");
            throw new IllegalArgumentException("运单不能为空");
        }
        //计算价格
        Map<Integer, Object> feeDetailsMap = dWaybillFeeService.getWaybillCostByCalc(
                waybill.getIstyleid().intValue(),waybill.getDepartureProvince(), waybill.getDepartureCity(),
                waybill.getDestProvince(), waybill.getDestCity(), waybill.getExtraCost());

        Map<Integer, Object>  returnMap = new HashMap<>();
        feeDetailsMap.forEach((key, value) -> {
            returnMap.put(Integer.valueOf(key),feeDetailsMap.get(key).toString());
        });

        if (MapUtils.isNotEmpty(feeDetailsMap)) {
//            DWaybill updateDWaybill = new DWaybill();
//            updateDWaybill.setId(waybill.getId());
            //总费用
            if (feeDetailsMap.containsKey(DWaybillFeeEnum.TOTAL_SHIPPING_COST.getValue())) {
                waybill.setConfirmTotalCost(new BigDecimal(feeDetailsMap.get(DWaybillFeeEnum.TOTAL_SHIPPING_COST.getValue()).toString()));
            }
            //总运费
            if (feeDetailsMap.containsKey(DWaybillFeeEnum.LABOR_COSTS.getValue())) {
                waybill.setTotalShippingCost(new BigDecimal(feeDetailsMap.get(DWaybillFeeEnum.LABOR_COSTS.getValue()).toString()));
            }
            //总油费
            if (feeDetailsMap.containsKey(DWaybillFeeEnum.TOTAL_OIL_COST.getValue())) {
                waybill.setTotalFuelCost(new BigDecimal(feeDetailsMap.get(DWaybillFeeEnum.TOTAL_OIL_COST.getValue()).toString()));
            }
            //剩余油费
            if (feeDetailsMap.containsKey(DWaybillFeeEnum.REMAINING_OIL_FEE.getValue())) {
                waybill.setRemainingOilFee(new BigDecimal(feeDetailsMap.get(DWaybillFeeEnum.REMAINING_OIL_FEE.getValue()).toString()));
            }
            //暂存油价
            if (feeDetailsMap.containsKey(DWaybillFeeEnum.MARKET_OIL_PRICE.getValue())) {
                //oilPercent暂用存储油价
                waybill.setOilPercent(new BigDecimal(feeDetailsMap.get(DWaybillFeeEnum.MARKET_OIL_PRICE.getValue()).toString()));
            }
            //暂存运输距离
            if (feeDetailsMap.containsKey(DWaybillFeeEnum.SHIP_DISTANCE.getValue())) {
                waybill.setDistance(new BigDecimal(feeDetailsMap.get(DWaybillFeeEnum.SHIP_DISTANCE.getValue()).toString()));
            }
            //单公里运价
            if (feeDetailsMap.containsKey(DWaybillFeeEnum.PRICE_PER_KM.getValue())) {
                waybill.setPricePerKm(new BigDecimal(feeDetailsMap.get(DWaybillFeeEnum.PRICE_PER_KM.getValue()).toString()));
            }
            //第一桶油费
            if (feeDetailsMap.containsKey(DWaybillFeeEnum.FIRST_BUCKET_OIL_FEE.getValue())) {
                waybill.setFirstFuelOilFee(new BigDecimal(feeDetailsMap.get(DWaybillFeeEnum.FIRST_BUCKET_OIL_FEE.getValue()).toString()));
            }
            //第一桶油量
            if (feeDetailsMap.containsKey(DWaybillFeeEnum.FIRST_BUCKET_OIL.getValue())) {
                waybill.setFirstFuelTotal(new BigDecimal(feeDetailsMap.get(DWaybillFeeEnum.FIRST_BUCKET_OIL.getValue()).toString()));
            }
            //单公里油价
            if (feeDetailsMap.containsKey(DWaybillFeeEnum.PRICE_OIL_PER_KM.getValue())) {
                waybill.setPriceOilPerKm(new BigDecimal(feeDetailsMap.get(DWaybillFeeEnum.PRICE_OIL_PER_KM.getValue()).toString()));
            }
            //总油量
            if (feeDetailsMap.containsKey(DWaybillFeeEnum.TOTAL_FUEL_CONSUMPTION.getValue())) {
                waybill.setTotalFuelConsumption(new BigDecimal(feeDetailsMap.get(DWaybillFeeEnum.TOTAL_FUEL_CONSUMPTION.getValue()).toString()));
            }

            this.updateSelective(waybill);
            
            //去掉运输距离
            if (feeDetailsMap.containsKey(DWaybillFeeEnum.SHIP_DISTANCE.getValue())) {
                feeDetailsMap.remove(DWaybillFeeEnum.SHIP_DISTANCE.getValue());
            }
            //去掉单公里油价
            if (feeDetailsMap.containsKey(DWaybillFeeEnum.PRICE_PER_KM.getValue())) {
                feeDetailsMap.remove(DWaybillFeeEnum.PRICE_PER_KM.getValue());
            }
            //去掉第一桶油费
            if (feeDetailsMap.containsKey(DWaybillFeeEnum.FIRST_BUCKET_OIL_FEE.getValue())) {
                feeDetailsMap.remove(DWaybillFeeEnum.FIRST_BUCKET_OIL_FEE.getValue());
            }
            //去掉第一桶油量
            if (feeDetailsMap.containsKey(DWaybillFeeEnum.FIRST_BUCKET_OIL.getValue())) {
                feeDetailsMap.remove(DWaybillFeeEnum.FIRST_BUCKET_OIL.getValue());
            }
            //去掉油品
            if (feeDetailsMap.containsKey(DWaybillFeeEnum.FUEL_TYPE.getValue())) {
                feeDetailsMap.remove(DWaybillFeeEnum.FUEL_TYPE.getValue());
            }
            //去掉单公里运价
            if (feeDetailsMap.containsKey(DWaybillFeeEnum.PRICE_OIL_PER_KM.getValue())) {
                feeDetailsMap.remove(DWaybillFeeEnum.PRICE_OIL_PER_KM.getValue());
            }
            //去掉总油量
            if(feeDetailsMap.containsKey(Integer.valueOf(DWaybillFeeEnum.TOTAL_FUEL_CONSUMPTION.getValue()))) {
                feeDetailsMap.remove(Integer.valueOf(DWaybillFeeEnum.TOTAL_FUEL_CONSUMPTION.getValue()));
            }
            feeDetailsMap.forEach((key, value) -> {

                /**
                 * 组装保存运单费用详情
                 */
                DWaybillFeeDetail feeDetail = new DWaybillFeeDetail();
                feeDetail.setCostType(typeEnum.getText());
                feeDetail.setWaybillId(waybill.getId());
                feeDetail.setFeeId(dWaybillFeeTypeService.getIdByConditions(String.valueOf(key)));
                feeDetail.setFeeName(DWaybillFeeEnum.getByValue(key).getText());
                feeDetail.setCost((BigDecimal) value);
                dWaybillFeeDetailService.add(feeDetail);
            });
        }
        return returnMap;
    }

    @Override
    public void updateAbandoned(Long waybillId, Integer messageCode, String message) throws Exception {
        LOGGER.info("DWaybillServiceImpl.updateAbandoned params : {}, {}, {}", waybillId, messageCode, message);

        if (null == waybillId || 0 == waybillId.longValue()) {
            LOGGER.error("DWaybillServiceImpl.updateAbandoned param waybillId must not be null");
            throw new IllegalArgumentException("运单主键不能为空");
        }

        if (null == messageCode || 0 == messageCode.intValue()) {
            LOGGER.error("DWaybillServiceImpl.updateAbandoned param messageCode must not be null");
            throw new IllegalArgumentException("错误码不能为空");
        }

        if (StringUtils.isBlank(message)) {
            LOGGER.error("DWaybillServiceImpl.updateAbandoned param message must not be null");
            throw new IllegalArgumentException("错误信息不能为空");
        }

        /**
         * 更新运单状态为废弃
         */
        DWaybill dWaybill = new DWaybill();
        dWaybill.setId(waybillId);
        dWaybill.setWaybillStatus(DWaybillStatusEnum.ABANDONED.getValue());
        this.updateSelective(dWaybill);

        /**
         * 保存废弃日志信息
         */
        DWaybillAbandonedLog log = new DWaybillAbandonedLog();
        log.setWaybillId(waybillId);
        log.setAbandonedCode(messageCode);
        log.setAbandonedReason(message);
        dWaybillAbandonedLogService.add(log);
    }

    // 发运时异步推送派单价格到tms
    private int pushOrderPriceInfo(DWaybill waybill,SUser user) throws Exception {
        LOGGER.info("DWaybillServiceImpl.pushOrderPrice params : {}, {}, {}", waybill, user);
        /**
         * 调用接口返回值
         */
        int returnCode = -1;

        OrderPriceInfo priceInfo = new OrderPriceInfo();


        //  获取d用户
        DUser dUser = dUserService.selectByPhone(user.getPhone());
        if (null == dUser) {
            LOGGER.error("DWaybillServiceImpl.pushMessage dUser must not be null");
            throw new BusinessException(TmsDispatchOptionCodeEnum.DRIVER_INFO_SYSTEM_ERROR.getValue() + "", TmsDispatchOptionCodeEnum.DRIVER_INFO_SYSTEM_ERROR.getText());
        }

        DUserExt dUserExt = dUserExtService.selectByUserId(dUser.getId());
        if (null == dUserExt) {
            LOGGER.error("DWaybillServiceImpl.pushMessage dUserExt must not be null");
            throw new BusinessException(TmsDispatchOptionCodeEnum.DRIVER_INFO_SYSTEM_ERROR.getValue() + "", TmsDispatchOptionCodeEnum.DRIVER_INFO_SYSTEM_ERROR.getText());
        }

        priceInfo.setVccard(dUserExt.getIdNo()); // 身份证号
//        priceInfo.setVcorderno(dUserExt.getTmsDriverNo());//司机编号
        priceInfo.setOrderlineId(waybill.getOrderLineId());//订单序号
        priceInfo.setOrderCode(waybill.getOrderCode());//订单编号
        priceInfo.setKilometer(waybill.getDistance().toString());//运输距离
        priceInfo.setFirstOilCapacity(waybill.getFirstFuelTotal().toString());//第一桶油量
        priceInfo.setFirstOilTotal(waybill.getFirstFuelOilFee().toString());//第一桶费用
        priceInfo.setOilPrice(waybill.getPricePerKm().toString());//单公里单价
        priceInfo.setOilCost(waybill.getConfirmTotalCost().toString());//总运费
        priceInfo.setCardOilTotal(waybill.getRemainingOilFee().toString());//应充卡油费
        priceInfo.setServiceWage("0");
        BigDecimal remainingOilFee = waybill.getRemainingOilFee().divide(waybill.getFirstFuelOilFee().divide(waybill.getFirstFuelTotal(), 2, BigDecimal.ROUND_UP), 2, BigDecimal.ROUND_UP);
        priceInfo.setCardOilCapacity(remainingOilFee.toString());//应充卡油量


        String tmsDriverNo = dUserExt.getTmsDriverNo();
        tmsDriverNo = StringUtils.isBlank(tmsDriverNo) == true ? ZL_DRIVER_PREFIX + dUserExt.getUserId() : tmsDriverNo;

        priceInfo.setVcorderno(tmsDriverNo); //司机编号


        // 中联结果分析处理-----开始----
        String data = this.pushOrderPrice(priceInfo);

        // 成功
        if (null != data) {
            JSONObject result = JSONObject.parseObject(data);
            return result.getInteger("messagecode");
        }
        // 中联结果分析处理-----结束----
        return returnCode;

    }


    @Override
    public String pushOrderPrice(OrderPriceInfo priceInfo)  throws Exception{
        LOGGER.info("pushOrderArrivalInfo params : {}", priceInfo);
        final String url = TmsUrlConstant.PUSH_ORDER_PRICE;
        Map<String, Object> paramsMap = new HashMap<>();
        this.bean2Map(paramsMap, priceInfo);
        return tmsOrderCallHistoryService.urlCall(url, TmsUrlTypeEnum.PUSH_ORDER_PRICE.getValue(), paramsMap, 10000);
    }



    @Override
    public Result<Object> pushPrice2tms(String orderCode) throws Exception{
        Result<Object>  result = new Result<>(true,"保存成功");
        LOGGER.info("DwaybillServiceImpl.pushPrice2tms orderCode:{}",orderCode);

        DWaybillExample example = new DWaybillExample();
        example.createCriteria().andOrderCodeEqualTo(orderCode);
        List<DWaybill> waybillList = dWaybillMapper.selectByExample(example);
        if(CollectionUtils.isEmpty(waybillList)){
            LOGGER.info("订单在知车中不存在: {}.", orderCode);
            result.setMessage("订单在知车中不存在");
        }
        DWaybill waybill =waybillList.get(0);
        SUser user = userService.getById(waybill.getUserId());
        if(null == user){
            LOGGER.info("未获取到司机信息: {}.", waybill.getUserId());
            result.setMessage("未获取到司机信息");
        }
        int returnCode = this.pushOrderPriceInfo(waybill,user);
        if(returnCode < 1){
            result.setSuccess(false);
            result.setMessage("保存失败");
        }
        return result;

    }

    @Override
    public Map<Integer, Object> getFirstBucketOil(DWaybill waybill) throws Exception{
        LOGGER.info("DWaybillServiceImpl.getFirstBucketOil params : {}", waybill);

        if (null == waybill) {
            LOGGER.error("DWaybillServiceImpl.getFirstBucketOil param waybill must not be null");
            throw new IllegalArgumentException("运单不能为空");
        }
        //计算第一桶油量
        Map<Integer, Object> waybillFirstBucketOilByCalc = dWaybillFeeService.getWaybillCostByCalc(
                waybill.getIstyleid().intValue(), waybill.getDepartureProvince(), waybill.getDepartureCity(),
                waybill.getDestProvince(), waybill.getDestCity(), waybill.getExtraCost());
        return waybillFirstBucketOilByCalc;

    }

    @Override
    public Map<String, Object> getQuickDispatchList(PageVo page, String orderCode,int waybillType, String beginDate, String endDate) throws Exception {
        LOGGER.info("DWaybillServiceImpl.getQuickDispatchList orderCode :{},waybillType:{}. ",orderCode,waybillType);

        // 查询运单信息
        List<Integer> statusList = new ArrayList<>();
        statusList.add(DWaybillStatusEnum.SAVE.getValue());

        Map<String, Object> map = new HashMap<>();

        try {
            Map<String, Object> paramsMap = new HashMap<>();
            String orderByClause = StringUtils.isNotBlank(page.getOrder()) == true ? page.getOrder()
                    : " dw.create_time asc";
            paramsMap.put("status", statusList);
            if (!Strings.isNullOrEmpty(orderCode)) {
                paramsMap.put("orderCode", orderCode);
            }
            if(waybillType==20){
                orderByClause = StringUtils.isNotBlank(page.getOrder()) == true ? page.getOrder()
                        : " dw.update_time DESC";
            }
            if (!Strings.isNullOrEmpty(beginDate)) {
                paramsMap.put("beginDate", beginDate);
            }
            if (!Strings.isNullOrEmpty(endDate)) {
                paramsMap.put("endDate", endDate);
            }
            paramsMap.put("waybillType", waybillType);
            page.setTotalRecord(this.dWaybillViewMapper.countByQuickDispatchList(paramsMap));
            paramsMap.put("limitStart", page.getStartIndex());
            paramsMap.put("limitEnd", page.getPageSize());
            paramsMap.put("orderByClause", orderByClause);
            List<DWaybillOringinalVo> dWaybillList = this.dWaybillViewMapper.getQuickDispatchList(paramsMap);
            map.put("page", page);
            map.put("dWaybillList", dWaybillList);
            return map;
        } catch (Exception e) {
            LOGGER.error("select current user dwaybill list error : {}.", e);
            throw new BusinessException("查询急发运单列表异常");
        }
    }

	@Override
	public void markQuickDispatch(Long orderId, String extraCost, String specialRequired, Integer waybillType)
			throws Exception {
		LOGGER.info("DWaybillServiceImpl.markQuickDispatch orderId :{}, extraCost :{}, specialRequired :{}, waybillType :{}", orderId, extraCost, specialRequired, waybillType);
        try {        	
            //查看一下运单是否被安排
            DWaybillExample example = new DWaybillExample();
            example.createCriteria().andIdEqualTo(orderId).andUserIdEqualTo(0L).andWaybillStatusEqualTo(DWaybillStatusEnum.SAVE.getValue());

            List<DWaybill> dWaybills = dWaybillMapper.selectByExample(example);
            if (CollectionUtils.isEmpty(dWaybills)) {
                LOGGER.error("DWaybillServiceImpl.markQuickDispatch dwaybill list must not be null");
                throw new BusinessException("此运单不能被置为急发单");
            }

        	Map<String, Object> paramsMap = new HashMap<>();
        	BigDecimal extraCostValue = new BigDecimal(extraCost);
        	extraCostValue.setScale(2, BigDecimal.ROUND_HALF_UP);
    		paramsMap.put("orderId", orderId);
            paramsMap.put("extraCost", extraCostValue);
            paramsMap.put("specialRequired", specialRequired);
            paramsMap.put("waybillType", waybillType);
            this.dWaybillViewMapper.markQuickDispatch(paramsMap);

            TmsQueueApi.removeOrder(orderId.toString(), dWaybills.get(0).getOrderLineId().toString());
//            TmsQueueOrderVo tqov = new TmsQueueOrderVo();
//            tqov.setFrom(dWaybills.get(0).getDepartureCity());
//            tqov.setTmsSerialNo(dWaybills.get(0).getOrderLineId().toString());
//            tqov.setTo(dWaybills.get(0).getDestCity());
//            tqov.setUrgent(dWaybills.get(0).getIsUrgent());
//            tqov.setWaybillId(orderId.toString());
//            tmsQueueService.appendQuickOrder(tqov);

        } catch (Exception e) {
            LOGGER.error("DWaybillServiceImpl.markQuickDispatch error : {}.", e);
            throw new BusinessException("标记急发运单异常");
        }
	}

    @Override
    public void competeQuickOrderList(Long orderId) throws Exception {
        Map<String, Object> map = new HashMap<>();
        //待匹配的运单
        TmsQueueOrderVo redisWaybill = null;
        //司机驾照是否匹配
        boolean licenseIsMatch = false;

        DWaybill waybill = null;
        UserShowVo currentUser = userService.getCurrentUser();
        if (null == currentUser) {
            throw new BusinessException("当前登录用户不存在");
        }

        waybill = this.getByPrimaryId(orderId);

        if (null == waybill) {
            LOGGER.error("DWaybillServiceImpl.competeQuickOrderList waybill is not exist");
            throw new BusinessException("查询运单出错");
        }
        if(0 != waybill.getUserId() || 0!= waybill.getWaybillStatus()){
            LOGGER.error("DWaybillServiceImpl.competeQuickOrderList waybill is have been dispatched");
            throw new BusinessException("对不起，您下手晚了");
        }
        if(20 != waybill.getWaybillType()){
            LOGGER.error("DWaybillServiceImpl.competeQuickOrderList waybill is not a quickWaybill");
            throw new BusinessException("对不起，此运单不是急发单");
        }
        if (validVcStyleLicense(waybill, currentUser)) {
            LOGGER.info("DWaybillServiceImpl.matchOrder driver license is match : {}, {}", waybill.getId(), currentUser.getPhone());
            licenseIsMatch = true;

        }
        //司机驾照不匹配
        if( !licenseIsMatch ){
            LOGGER.error("DWaybillServiceImpl.matchOrder driver lines not match");
            throw new BusinessException(TmsDispatchOptionCodeEnum.DRIVER_LICENSE_NOT_MATCH.getValue()+"", TmsDispatchOptionCodeEnum.DRIVER_LICENSE_NOT_MATCH.getText());
        }

        String userPhone = currentUser.getPhone();

        this.dispatchDWaybill(waybill, userPhone, false);

        /**
         * 派单成功时移除急发运单
         */
        TmsQueueApi.removeDriver(userPhone);
        // push消息给司机 TODO司机发短信注释
        sendMessageService.sendDispatchMessage(waybill.getOrderCode(), currentUser.getPhone());
    }


    /**
     * 校验准驾车型
     *
     * @param waybill  订单信息
     * @param driver   司机信息
     * @return
     */
    private boolean validVcStyleLicense(DWaybill waybill, UserShowVo driver) throws Exception {

        LOGGER.info("TmsQueueDimensionServiceImpl.validVcStyleLicense params : {}, {}", waybill, driver);

        if (null == waybill) {
            LOGGER.error("TmsQueueDimensionServiceImpl.validVcStyleLicense params waybill must not null");
            throw new BusinessException("300", "运单信息为空");
        }
        if (null == driver) {
            LOGGER.error("TmsQueueDimensionServiceImpl.validVcStyleLicense params driver must not null");
            throw new BusinessException("300", "司机信息为空");
        }

        // 驾照信息
        DUser dUser = dUserService.selectByPhone(driver.getPhone());
        DUserLicenseExample dule = new DUserLicenseExample();
        dule.createCriteria().andUserIdEqualTo(dUser.getId());
        List<DUserLicense> dulList = this.dUserLicenseMapper.selectByExample(dule);
        StringBuffer sb = new StringBuffer("");
        for (DUserLicense dul : dulList) {
            sb.append(dul.getLicenseName()).append(",");
        }
        String licenseStr = sb.toString();
        if (licenseStr.endsWith(",")) {
            licenseStr = licenseStr.substring(0, licenseStr.length() - 1);
        }

        /**
         * 判断司机有没有驾照类型
         */


        if (StringUtils.isBlank(licenseStr) || !(licenseStr.split(",").length > 0)) {

            LOGGER.info("TmsQueueDimensionServiceImpl.validVcStyleLicense driver has no license type : {}", driver.getPhone());
            throw new BusinessException(TmsDispatchOptionCodeEnum.DRIVER_HAS_NO_LICENSE.getValue() + "", TmsDispatchOptionCodeEnum.DRIVER_HAS_NO_LICENSE.getText());
        }

        //获得准驾车型
        DWaybill dWaybill = this.selectByOrderLineId(waybill.getOrderLineId());
        if ( null == dWaybill ) {
            LOGGER.info("TmsQueueDimensionServiceImpl.validVcStyleLicense dWaybill must not be null");
            throw new BusinessException(TmsDispatchOptionCodeEnum.WAYBILL_IS_NULL.getValue() + "", TmsDispatchOptionCodeEnum.WAYBILL_IS_NULL.getText());

        }

        DWaybillVehicle waybillVehicle = dWaybillVehicleService.getByDWaybillId(dWaybill.getId());

        String vcstyleno = waybillVehicle.getVehicleTypeCode();

        DVcstyleLicense dVcstyleLicense = this.getVcStyleByStyleCode(vcstyleno);
        if (null == dVcstyleLicense || StringUtils.isBlank(dVcstyleLicense.getLicense())) {
            LOGGER.info("TmsQueueDimensionServiceImpl.validVcStyleLicense driver has no license base data : {}", driver.getPhone());
            throw new BusinessException(TmsDispatchOptionCodeEnum.WAYBILL_VEHICLE_HAS_NO_LICENSE_BASE_DATA.getValue() + "", TmsDispatchOptionCodeEnum.WAYBILL_VEHICLE_HAS_NO_LICENSE_BASE_DATA.getText());

        }

        String license = dVcstyleLicense.getLicense().toUpperCase();
        licenseStr = licenseStr.toUpperCase();
        String[] driverVoLicenseArray = licenseStr.split(",");

//        //是否匹配
//        boolean isMatch = false;

        for (int i = 0; i < driverVoLicenseArray.length; i++) {
            if (license.contains(driverVoLicenseArray[i])) {
//                isMatch = true;
                return true;
            }
        }
        return false;
    }


    public DVcstyleLicense getVcStyleByStyleCode(String vcCode){
        LOGGER.info("getVcStyleByStyleCode params vcCode: {}",vcCode);
        DVcstyleLicenseExample dVcstyleLicenseExample = new DVcstyleLicenseExample();
        dVcstyleLicenseExample.createCriteria().andVcstylecodeEqualTo(vcCode);
        List<DVcstyleLicense> searchDVcstyleLicenseList = dVcstyleLicenseMapper.selectByExample(dVcstyleLicenseExample);

        if( CollectionUtils.isNotEmpty(searchDVcstyleLicenseList) ){
            return searchDVcstyleLicenseList.get(0);
        }
        return null;
    }

    private void handleError(DWaybill waybill, UserShowVo driver, String messageCode, Exception e) throws Exception {
        LOGGER.info("TmsQueueDimensionServiceImpl.handleError param : {}, {}, {}", waybill, driver, messageCode);

        /**
         * 错误时运单的处理
         */
        this.handleErrorForDWaybill(waybill, driver, e);

        if (messageCode.startsWith("1")) {

            String userPhone = driver.getPhone();

            boolean isRemoveDriver = true;

            /**
             * DRIVER_INFO_ERROR(0, "获取司机关联信息失败"),
             * DRIVER_HAS_NO_IDCARD(101, "需要提供身份证号"),
             * DRIVER_HAS_NO_PHONE_NO(102, "需要提供手机号"),
             * DRIVER_UPDATE_INFO_ERROR(103, "读取/更新司机信息错误"),
             * DRIVER_IS_NOT_TMS_DRIVER(104, "非知车司机，不可以安排"),
             * DRIVER_HAS_NO_LICENSE(106, "司机缺少驾照类型"),
             * DRIVER_LICENSE_NOT_MATCH(107, "司机驾照不匹配"),
             * DRIVER_LICENSE_NOT_MATCH(107, "司机线路不匹配"),
             * DRIVER_HAS_NO_INTENTIONA_LINE(108, "司机缺少意向线路"),
             * DRIVER_IS_DISABLE(109, "司机不可用"),
             * DRIVER_ALREADY_HAVE_WAYVILL(110, "司机已经有未完成的运单"),
             * DRIVER_INFO_SYSTEM_ERROR(111, "系统司机信息错误"),
             */

            if (messageCode.equals(TmsDispatchOptionCodeEnum.DRIVER_INFO_ERROR.getValue() + "")) {
                this.sendMessageService.sendByTplId(JavaSmsApi.DRIVER_INFO_ERROR, userPhone);
            } else if (messageCode.equals(TmsDispatchOptionCodeEnum.DRIVER_HAS_NO_IDCARD.getValue() + "")) {
                sendMessageService.sendByTplId(JavaSmsApi.DRIVER_HAS_NO_IDCARD, userPhone);
            } else if (messageCode.equals(TmsDispatchOptionCodeEnum.DRIVER_HAS_NO_PHONE_NO.getValue() + "")) {
                sendMessageService.sendByTplId(JavaSmsApi.DRIVER_HAS_NO_PHONE_NO, userPhone);
            } else if (messageCode.equals(TmsDispatchOptionCodeEnum.DRIVER_UPDATE_INFO_ERROR.getValue() + "")) {
                sendMessageService.sendByTplId(JavaSmsApi.DRIVER_UPDATE_INFO_ERROR, userPhone);
            } else if (messageCode.equals(TmsDispatchOptionCodeEnum.DRIVER_IS_NOT_TMS_DRIVER.getValue() + "")) {
                sendMessageService.sendByTplId(JavaSmsApi.DRIVER_IS_NOT_TMS_DRIVER, userPhone);
            } else if (messageCode.equals(TmsDispatchOptionCodeEnum.DRIVER_HAS_NO_LICENSE.getValue() + "")) {
                sendMessageService.sendByTplId(JavaSmsApi.DRIVER_HAS_NO_LICENSE, userPhone);
            } else if (messageCode.equals(TmsDispatchOptionCodeEnum.DRIVER_LICENSE_NOT_MATCH.getValue() + "") || messageCode.equals(TmsDispatchOptionCodeEnum.DRIVER_LINE_NOT_MATCH.getValue() + "")) {

                isRemoveDriver = false;

                /**
                 * 保持司机位置，抓取司机是index+1
                 */
//                this.driverIndex += 1;

//                sendMessageService.sendByTplId(JavaSmsApi.DRIVER_LICENSE_NOT_MATCH, userPhone);
            } else if (messageCode.equals(TmsDispatchOptionCodeEnum.DRIVER_HAS_NO_INTENTIONA_LINE.getValue() + "")) {
                sendMessageService.sendByTplId(JavaSmsApi.DRIVER_HAS_NO_INTENTIONA_LINE, userPhone);
            } else if (messageCode.equals(TmsDispatchOptionCodeEnum.DRIVER_IS_DISABLE.getValue() + "")) {
                sendMessageService.sendByTplId(JavaSmsApi.DRIVER_IS_DISABLE, userPhone);
            } else if (messageCode.equals(TmsDispatchOptionCodeEnum.DRIVER_ALREADY_HAVE_WAYBILL.getValue() + "")) {
                sendMessageService.sendByTplId(JavaSmsApi.DRIVER_ALREADY_HAVE_WAYVILL, userPhone);
            } else if (messageCode.equals(TmsDispatchOptionCodeEnum.DRIVER_INFO_SYSTEM_ERROR.getValue() + "")) {
//                sendMessageService.sendByTplId(JavaSmsApi.DRIVER_INFO_SYSTEM_ERROR, userPhone);
            } else if (messageCode.equals(TmsDispatchOptionCodeEnum.DRIVER_WRONG_PHONE_NO.getValue() + "")) {
                //do nth
            }

            if (isRemoveDriver) {
                /**
                 * 异常时移除司机
                 */
                //TmsQueueApi.removeDriver(driver);
            }

        } else if (messageCode.startsWith("3")) {

            /**
             * 废弃运单
             *
             * NO_TMS_ORDER(302, "该订单非人送订单，请确定数据"),//TMS
             * NO_TMS_ORDER_TEAM(303, "该订单对应的指令不属于人送提车队，不可以安排"),//TMS
             * IS_SEND_ORDER(304, "该订单已发车，不可以安排"),//TMS
             * ADD_DRIVER_ERROR(305, "新增司机更换表 错误"),//TMS
             * WAYBILL_IS_NULL(309, "运单为空"),
             * WAYBILL_HAS_BEEN_SENT(310, "运单已经安排给其他司机"),
             */
            if (messageCode.equals(TmsDispatchOptionCodeEnum.NO_TMS_ORDER.getValue() + "")
                    || messageCode.equals(TmsDispatchOptionCodeEnum.NO_TMS_ORDER_TEAM.getValue() + "")
                    || messageCode.equals(TmsDispatchOptionCodeEnum.IS_SEND_ORDER.getValue() + "")
                    || messageCode.equals(TmsDispatchOptionCodeEnum.ADD_DRIVER_ERROR.getValue() + "")
                    || messageCode.equals(TmsDispatchOptionCodeEnum.WAYBILL_IS_NULL.getValue() + "")
                    || messageCode.equals(TmsDispatchOptionCodeEnum.WAYBILL_HAS_BEEN_SENT.getValue() + "")) {

                this.updateAbandoned(waybill.getId(), Integer.parseInt(messageCode),
                        TmsDispatchOptionCodeEnum.getByValue(Integer.parseInt(messageCode)).getText());
            }

            /**
             *  异常时移除队列订单
             */
           // TmsQueueApi.removeOrder(redisWaybill);
        }

    }

    private void handleErrorForDWaybill(DWaybill waybill, UserShowVo driver, Exception e) {
        LOGGER.info("TmsQueueDimensionServiceImpl.handleErrorForDWaybill params : {}, {}, {}", waybill, driver, e);

        /**
         * FIXME
         * 逻辑错误，应该区分错误是由tms返回，还是由系统内部判断返回
         */
        if (null != waybill) {
            this.updateIsError(waybill.getId());
        }

        /**
         * 保存派单错误信息
         */
        DWaybillErrorMsg errorMsg = new DWaybillErrorMsg();
        if (null != waybill) {
            errorMsg.setWaybillId(waybill.getId());
            errorMsg.setWaybillLineId(waybill.getOrderLineId().intValue());
        }
        if (null != driver) {
            /**
             *  qichao
             *  FIXME 整个账号体系需要重构
             *  校验当前司机是否存在，若不存在，则移除司机（当前是从redis取司机信息，根据司机的手机号，去mysql取意向路线，若后台变更了司机的手机号，则会NPE）
             */
            if(Objects.equals(userService.getUserByPhone(driver.getPhone()),null)){
                LOGGER.info("============司机手机号已在后台变更，日志表中不记录ID==============");
                errorMsg.setUserId(null);
            }else{
                errorMsg.setUserId(userService.getUserByPhone(driver.getPhone()).getId());
            }
            errorMsg.setUserPhone(driver.getPhone());
        }
        errorMsg.setIsHandle(false);
        if (e instanceof BusinessException) {
            errorMsg.setErrCode(((BusinessException) e).getMessageCode());
        }
        errorMsg.setErrMsg(e.getMessage());
       // dWaybillErrorMsgService.add(errorMsg);
    }

    /**
     * 异步推送司机信息和第一桶油，油箱容积等基础信息
     * @param waybill
     * @param orderLineId
     * @param user
     * @return
     * @throws Exception
     */
	private int pushMessage(DWaybill waybill, Long orderLineId, SUser user) throws Exception {
        LOGGER.info("DWaybillServiceImpl.pushMessage params : {}, {}, {}", waybill, orderLineId, user);

        /**
         * 调用接口返回值
         */
        int returnCode = -1;

        OrderDistributableInfo distributableInfo = new OrderDistributableInfo();

        //  获取d用户
        DUser dUser = dUserService.selectByPhone(user.getPhone());
        if (null == dUser) {
            LOGGER.error("DWaybillServiceImpl.pushMessage dUser must not be null");
            throw new BusinessException(TmsDispatchOptionCodeEnum.DRIVER_INFO_SYSTEM_ERROR.getValue() + "", TmsDispatchOptionCodeEnum.DRIVER_INFO_SYSTEM_ERROR.getText());
        }

        DUserExt dUserExt = dUserExtService.selectByUserId(dUser.getId());
        if (null == dUserExt) {
            LOGGER.error("DWaybillServiceImpl.pushMessage dUserExt must not be null");
            throw new BusinessException(TmsDispatchOptionCodeEnum.DRIVER_INFO_SYSTEM_ERROR.getValue() + "", TmsDispatchOptionCodeEnum.DRIVER_INFO_SYSTEM_ERROR.getText());
        }

        distributableInfo.setVcname(dUserExt.getRealName()); // 司机姓名
        distributableInfo.setVcnative(dUserExt.getBirthplace()); // 籍贯
        distributableInfo.setDtbirthday(dUserExt.getBirthday()); // 出生年月
        distributableInfo.setVccard(dUserExt.getIdNo()); // 身份证号
        distributableInfo.setVchometel(dUserExt.getHomePhone()); // 家庭电话
        distributableInfo.setVchomeaddress(dUserExt.getHomeAddress()); // 住址
        distributableInfo.setVcvouch(dUserExt.getGuarantor()); // 担保人

        /**
         * 获取司机驾照类型
         */
        DUserLicense dUserLicense = dUserLicenseService.selectByUserId(dUser.getId());

        if (null == dUserLicense) {
            LOGGER.error("DWaybillServiceImpl.pushMessage user license must not be null");
            throw new BusinessException(TmsDispatchOptionCodeEnum.DRIVER_HAS_NO_LICENSE.getValue() + "", TmsDispatchOptionCodeEnum.DRIVER_HAS_NO_LICENSE.getText());
        }


        Map<Integer, Object> feeMaps = this.getScMap(waybill);

        distributableInfo.setDtfirstget(dUserLicense.getReceiveTime()); // 驾照初领时间
        distributableInfo.setVcdept(dUserLicense.getLicenseDept()); // 驾照发证机关
        distributableInfo.setVcdrivestyle(dUserLicense.getLicenseName()); // 驾照类型

        distributableInfo.setVcorderno(waybill.getOrderCode());
        distributableInfo.setOrderilineid(orderLineId);
        distributableInfo.setVcmobile(user.getPhone()); // 手机号
        distributableInfo.setAssigntime(new Date()); // 派单时间

        String tmsDriverNo = dUserExt.getTmsDriverNo();
        tmsDriverNo = StringUtils.isBlank(tmsDriverNo) == true ? ZL_DRIVER_PREFIX + dUserExt.getUserId() : tmsDriverNo;

        distributableInfo.setVcdriverno(tmsDriverNo); // 司机编号
        distributableInfo.setVccommunity(""); // 所属社区
        distributableInfo.setIrateid(1); // 司机等级
        
        distributableInfo.setKm(waybill.getDistance()); //距离
        distributableInfo.setFuelquota(waybill.getFirstFuelTotal()); // 第一箱油
        distributableInfo.setFuelunitprice(waybill.getPriceOilPerKm()); // 油品单价
        distributableInfo.setFuelconsumptionstandard(new BigDecimal(feeMaps.get(DWaybillFeeEnum.OIL_CONSUMPTION.getValue()).toString())); // 百公里油耗标准
        distributableInfo.setFuelremainvol(new BigDecimal(feeMaps.get(DWaybillFeeEnum.REMAIN_OIL.getValue()).toString())); // 剩余油量
        distributableInfo.setFueltankvol(new BigDecimal(feeMaps.get(DWaybillFeeEnum.TANKVOLUME.getValue()).toString())); // 油箱容积
        distributableInfo.setFuelclass(feeMaps.get(DWaybillFeeEnum.FUEL_TYPE.getValue()).toString()); // 油品

        // 中联结果分析处理-----开始----
        String data = this.pushOrderDistributableInfoToTms(distributableInfo);

        // 成功
        if (null != data) {
            JSONObject result = JSONObject.parseObject(data);
            return result.getInteger("messagecode");
        }
        // 中联结果分析处理-----结束----
        return returnCode;
	}

    /**
     * 获取费用基础数据
     * @param waybill
     * @return
     * @throws Exception
     */
    private Map<Integer, Object> getScMap( DWaybill waybill) throws Exception {
        /**
         * 查询车型分类
         */
        DVehicleClassify dVehicleClassify = dVehicleClassifyService.selectByVehicleClassifyId(waybill.getIstyleid().intValue());
        if (null == dVehicleClassify) {
            LOGGER.error("DWaybillFeeServiceImpl.getWaybillFirstBucketOil dVehicleClassifies dVehicleClassify must not be null");
            throw new BusinessException("车型分类不能为空");
        }

        /**
         * 查询车型油耗
         */
        ScPriceconfOc scPriceconfOc = scPriceconfOcService.selectEffective(dVehicleClassify.getId(), new Date());
        if ( null == scPriceconfOc ) {
            LOGGER.error("DWaybillFeeServiceImpl.getWaybillFirstBucketOil scPriceconfOcs must not be null");
            throw new BusinessException("车型油耗不能为空");
        }

        /**
         * 查询油箱容积
         */
        ScBaseCvTankvolumeVo scBaseCvTankvolume=scBaseCvTankvolumeService.selectCvTankvolumeByCvTypeId(waybill.getIstyleid().intValue());
        if(null == scBaseCvTankvolume){
            LOGGER.error("DWaybillFeeServiceImpl.getWaybillFirstBucketOil scBaseCvTankvolume must not be null");
            throw new BusinessException("油箱容积不能为空");
        }

        Integer fuelTypeId = dVehicleClassify.getFuelTypeId(); // 油品id
        DFuelType dFuelType = dFuelTypeMapper.selectByPrimaryKey(fuelTypeId);
        String fuleName = dFuelType.getFuelName(); // 油品

        Map<Integer, Object> fees = new HashedMap();
        fees.put(DWaybillFeeEnum.OIL_CONSUMPTION.getValue(), scPriceconfOc.getCurrentValue());//车型油耗 = 6 2017-06-06 11:22:55  ligl
        fees.put(DWaybillFeeEnum.REMAIN_OIL.getValue(), waybill.getTotalFuelConsumption().subtract(waybill.getFirstFuelTotal()));//剩余油量 = 7 2017-06-06 11:22:55  ligl
        fees.put(DWaybillFeeEnum.TANKVOLUME.getValue(), scBaseCvTankvolume.getTankVolume());//车型容积 = 8 2017-06-06 11:22:55  ligl
        fees.put(DWaybillFeeEnum.FUEL_TYPE.getValue(), fuleName);//油品 = 9 2017-06-06 11:22:55  ligl

        return fees;

    }

    @Override
    public List<DWaybill> selectNoDeliveredDWaybill(){
        DWaybillExample example = new DWaybillExample();
        List<Long> lngUserId=Arrays.asList(0L,-1L);
        List<Integer> intStatus=Arrays.asList(0,100);
        example.createCriteria().andUserIdIn(lngUserId).andWaybillStatusIn(intStatus);
        return this.selectByExample(example);
    }
}
